2010-09-20 283 views
0

我有一张表保持用户对项目的评分。 我想让每个用户只评价一次,有没有办法强制数据库不允许重复itemId和userId?关系数据库设计 - 一个表中的双主键?

alt text

我不希望每个人字段作为主键。 我希望主键同时基于它们两个。 例如有一排:

itemId= 1 & userId = 1 

以下应被允许:

itemId= 2 & userId = 1 
itemId= 1 & userId = 2 

下不应当被允许:

itemId= 1 & userId = 1 
+0

我怀疑把这个逻辑放在数据库中。似乎它应该属于验证代码的其余部分。 – CurtainDog 2010-09-20 05:38:50

回答

3

是。在itemId和userId上创建一个主键。

要在T-SQL(SQL Server)的,你会使用类似这样:

CREATE TABLE rating (
    itemId int NOT NULL 
    CONSTRAINT fk_rating_item FOREIGN KEY REFERENCES item (itemId), 
    userId int NOT NULL 
    CONSTRAINT fk_rating_user FOREIGN KEY REFERENCES [user] (userId), 
    thumbsUp int, 
    thumbsDown int, 
    CONSTRAINT pk_rating PRIMARY KEY (itemId, userId) 
) 

(这里假设你的项目表“项”和您的用户表是“用户”)

我不确定为什么你对拇指和拇指都有价值?如果这是一个布尔值,那么您可能只需要一个:如果赞成为0,那么无论如何这是有效的。

编辑:组合键定义

当你创建一个表上的两列的主键,这意味着它仅需要对两个值唯一的,也就是说,它会允许任何数量的只要每个userId不同,就会有相同itemId的行,反之亦然。

这是两者的组合,必须是唯一的,而不是密钥的每个部分。

+2

使用复合主键的一个缺点是,如果与其他表有关系,那么最终也需要复合外键。这可能不是这个例子中的一个因素,但在其他情况下可能会变得复杂。假设每个评分有多个段落和许多附件,每个附件都有自己的表格。那么这些表需要itemId和userId列,并且您必须小心地在更新和查询中使用这两个键。或者,您可以为评分表使用一个代理键,并通过约束强制itemId,userId唯一性。 – 2010-09-20 01:34:36

+0

Alex,你说的是真的。但是,如果您将主题分析为实体和关系,并将所有属性与此ER框架相关联,然后以相当直接的方式将这些属性组合到关系中,则最终将获得从未具有实体引用关系或关系的表引用其他关系。至少,不是一开始。 – 2010-09-20 05:24:22

0

大多数数据库将允许由多个列组成的复合主键。你正在使用哪个数据库?

一个有趣的,相关的讨论:What are the down sides of using a composite/compound primary key?

MySQL的类型例如:

createuserratings.sql 
CREATE TABLE USERRATINGS 
( 
    itemId  INT NOT NULL, 
    userId  INT NOT NULL, 
    thumbsUp INT NOT NULL, 
    thumbsDown INT NOT NULL, 
    PRIMARY KEY (itemID, userID) 
); 

执行搜索复合/复合主键MySQL的文档中,你应该得到大量的信息(我不不使用mySQL)。

+0

我正在使用mysql – aryaxt 2010-09-20 00:53:06

0

使用复合主键(由2列组成的主键)。

CREATE TABLE Rating 
(
itemID  INT NOT NULL 
,userID  INT NOT NULL 
,thumbsUP INT NOT NULL 
,thumbsDown INT NOT NULL 
,PRIMARY KEY (itemID, userID) 
); 
+0

谢谢,那么如果我不想有一个复合主键,我会做什么不同? – aryaxt 2010-09-20 01:04:55

+1

我会说你不会做任何不同的事情。 Rating是一个联结表,在这种情况下,是建立User表和Item表之间关系的唯一方法。 – 2010-09-20 01:11:15