我有一张表保持用户对项目的评分。 我想让每个用户只评价一次,有没有办法强制数据库不允许重复itemId和userId?关系数据库设计 - 一个表中的双主键?
我不希望每个人字段作为主键。 我希望主键同时基于它们两个。 例如有一排:
itemId= 1 & userId = 1
以下应被允许:
itemId= 2 & userId = 1
itemId= 1 & userId = 2
下不应当被允许:
itemId= 1 & userId = 1
我有一张表保持用户对项目的评分。 我想让每个用户只评价一次,有没有办法强制数据库不允许重复itemId和userId?关系数据库设计 - 一个表中的双主键?
我不希望每个人字段作为主键。 我希望主键同时基于它们两个。 例如有一排:
itemId= 1 & userId = 1
以下应被允许:
itemId= 2 & userId = 1
itemId= 1 & userId = 2
下不应当被允许:
itemId= 1 & userId = 1
是。在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的行,反之亦然。
这是两者的组合,必须是唯一的,而不是密钥的每个部分。
使用复合主键的一个缺点是,如果与其他表有关系,那么最终也需要复合外键。这可能不是这个例子中的一个因素,但在其他情况下可能会变得复杂。假设每个评分有多个段落和许多附件,每个附件都有自己的表格。那么这些表需要itemId和userId列,并且您必须小心地在更新和查询中使用这两个键。或者,您可以为评分表使用一个代理键,并通过约束强制itemId,userId唯一性。 – 2010-09-20 01:34:36
Alex,你说的是真的。但是,如果您将主题分析为实体和关系,并将所有属性与此ER框架相关联,然后以相当直接的方式将这些属性组合到关系中,则最终将获得从未具有实体引用关系或关系的表引用其他关系。至少,不是一开始。 – 2010-09-20 05:24:22
大多数数据库将允许由多个列组成的复合主键。你正在使用哪个数据库?
一个有趣的,相关的讨论: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)。
我正在使用mysql – aryaxt 2010-09-20 00:53:06
使用复合主键(由2列组成的主键)。
CREATE TABLE Rating
(
itemID INT NOT NULL
,userID INT NOT NULL
,thumbsUP INT NOT NULL
,thumbsDown INT NOT NULL
,PRIMARY KEY (itemID, userID)
);
谢谢,那么如果我不想有一个复合主键,我会做什么不同? – aryaxt 2010-09-20 01:04:55
我会说你不会做任何不同的事情。 Rating是一个联结表,在这种情况下,是建立User表和Item表之间关系的唯一方法。 – 2010-09-20 01:11:15
我怀疑把这个逻辑放在数据库中。似乎它应该属于验证代码的其余部分。 – CurtainDog 2010-09-20 05:38:50