2015-02-06 122 views
0

我有一张书籍表,其中存储了书籍ID和标题,作者等,具有客户ID的客户表(PK),客户姓名,生日。然后是一个交易表,其中包括BookId和CustomerID作为外键。此事务表的主键是两个外键列。MySQL:使用引用由外键组成的主键的外键创建表

现在的问题是,我正在创建基于发生的交易的书评分表(因此,客户不能评价他们不拥有的书籍,或同一书籍两次)。此表格必须包含bookID,客户ID和评分信息。我试图限制表,以便每个bookID和customerID行必须引用事务表中的现有行。但是,迄今为止我尝试过的所有限制都不起作用。任何帮助都将不胜感激。

这里是我的表的那一刻:

CREATE TABLE eBook 
(  BookTitle VARCHAR(50), 
    BookID  CHAR(13) NOT NULL, 
    BookPub  CHAR(4) NOT NULL, 
    BookDate DATE NOT NULL, 
    BookHard BOOL NOT NULL, 
    BookSize INT NOT NULL, 
CONSTRAINT PKBookID PRIMARY KEY (BookID) 
); 

CREATE TABLE customer 
(  CustID  CHAR(9) NOT NULL, 
    CustSSN  CHAR(11) NULL, 
    CustName VARCHAR(50) NOT NULL, 
    CustBirth INT(4) NOT NULL, 
CONSTRAINT PKCustID PRIMARY KEY (CustID), 
CONSTRAINT UniqSSN UNIQUE (CustSSN) 
); 

CREATE TABLE Buys 
( BuysID  CHAR(5) NOT NULL      
BookID  CHAR(13) NOT NULL, 
CustID  CHAR(9) NOT NULL, 
TransDate DATETIME NOT NULL, 
Price  DECIMAL(5,2) NOT NULL, 
CONSTRAINT FK1 FOREIGN KEY (BookID) REFERENCES eBook (BookID) 
ON DELETE CASCADE 
ON UPDATE CASCADE, 
CONSTRAINT FK2 FOREIGN KEY (CustID) REFERENCES customer (CustID) 
ON DELETE CASCADE 
ON UPDATE CASCADE, 
CONSTRAINT PKBuys PRIMARY KEY (BookID, CustID) 
); 

CREATE TABLE Rating 
( BookID  CHAR(13) NOT NULL, 
CustID  CHAR(9) NOT NULL, 
RatingID CHAR(5) NOT NULL, 
Rating  INT(1) NOT NULL, 
RatingDate DATE NOT NULL, 
CONSTRAINT FK13 FOREIGN KEY (BookID, CustID) REFERENCES buys (BookID, CustID) 
ON DELETE CASCADE 
ON UPDATE CASCADE, 
CONSTRAINT PKRating PRIMARY KEY (RatingID) 
); 
+0

不要忘记添加你的问题,你已经尝试过(如在实际的创建表或查询或任何可能),所以人们可以轻松地帮助你。 – Prix 2015-02-06 20:31:24

+0

虽然有些人会认为这不是最正确的方法,但我会做的只是将评级列添加到购买表。用户可以通过这种方式对购买或不进行评级,但他们只能对自己的购买进行评级。 – mrunion 2015-02-06 20:36:50

+0

在'Buys'表中有一个自动增量ID作为主键可能会更好,并将它用作'Rating'表中的外键。您仍然可以在'(BookID,CustID)'上使用唯一的密钥来防止重复购买。 – Barmar 2015-02-06 20:39:34

回答

0

您的Rating表上已经有一个外键,它们应该约束Rating行以对应Buys行。我想这个问题必须与你的另一个目标一致,即顾客不能两次对同一本书进行评分。关于这一点,我猜你对外键有一个误解:它们必须在目标表中唯一,但它们在引用端不必自动唯一。

为防止具有BookIDCustomerID相同的组合多Rating行,你需要在Rating表的附加UNIQUE约束,命名这些列。或者,您可以为Rating表提供一个由这些列组成的复合主键。无论采用哪种方式,您都将拥有单独的约束条件,其中一个确定引用表中这些列的唯一性,另一个约束它们出现在Buys表中的对。

+0

非常感谢您的洞察!这完美的作品! – seriestoo2 2015-02-06 21:01:07

0

您可以创建一个多列外键引用上http://dev.mysql.com/doc/refman/5.0/en/create-table-foreign-keys.html 这应该做的伎俩记录。

您的示例代码包含错误。您在购买表中缺少(,)。

CREATE TABLE eBook 
(  BookTitle VARCHAR(50), 
    BookID  CHAR(13) NOT NULL, 
    BookPub  CHAR(4) NOT NULL, 
    BookDate DATE NOT NULL, 
    BookHard BOOL NOT NULL, 
    BookSize INT NOT NULL, 
CONSTRAINT PKBookID PRIMARY KEY (BookID) 
); 

CREATE TABLE customer 
(  CustID  CHAR(9) NOT NULL, 
    CustSSN  CHAR(11) NULL, 
    CustName VARCHAR(50) NOT NULL, 
    CustBirth INT(4) NOT NULL, 
CONSTRAINT PKCustID PRIMARY KEY (CustID), 
CONSTRAINT UniqSSN UNIQUE (CustSSN) 
); 

CREATE TABLE Buys 
( BuysID  CHAR(5) NOT NULL,     
BookID  CHAR(13) NOT NULL, 
CustID  CHAR(9) NOT NULL, 
TransDate DATETIME NOT NULL, 
Price  DECIMAL(5,2) NOT NULL, 
CONSTRAINT FK1 FOREIGN KEY (BookID) REFERENCES eBook (BookID) 
ON DELETE CASCADE 
ON UPDATE CASCADE, 
CONSTRAINT FK2 FOREIGN KEY (CustID) REFERENCES customer (CustID) 
ON DELETE CASCADE 
ON UPDATE CASCADE, 
CONSTRAINT PKBuys PRIMARY KEY (BookID, CustID) 
); 

CREATE TABLE Rating 
( BookID  CHAR(13) NOT NULL, 
CustID  CHAR(9) NOT NULL, 
Rating  INT(1) NOT NULL, 
RatingDate DATE NOT NULL, 
CONSTRAINT FK13 FOREIGN KEY (BookID, CustID) REFERENCES buys (BookID, CustID) 
ON DELETE CASCADE 
ON UPDATE CASCADE, 
CONSTRAINT PKRating PRIMARY KEY (BookID, CustID) 
); 

使用此更正的ddl时,表格创建得很好。

我已经创建了一些测试数据

insert into `ebook`(`BookTitle`,`BookID`,`BookPub`,`BookDate`,`BookHard`,`BookSize`) values ('grey','1','ME','2015-02-06',1,10); 
insert into `customer`(`CustID`,`CustSSN`,`CustName`,`CustBirth`) values ('1','daCust','Cust',1974); 
insert into `buys`(`BuysID`,`BookID`,`CustID`,`TransDate`,`Price`) values ('1','1','1','2015-02-06 00:00:00',10.00); 
insert into `rating`(`BookID`,`CustID`,`RatingID`,`Rating`,`RatingDate`) values ('1','1','1',1,'2015-02-06'); 

现在加入下面的数据会导致错误由于外键约束。

insert into `rating`(`BookID`,`CustID`,`RatingID`,`Rating`,`RatingDate`) values ('7','3','1',1,'2015-02-06'); 

为了确保用户可以每本书只添加一个评价,你应该上的字段的BookID和客户ID或设置这些领域的主键添加唯一约束。在上面的工作代码示例中,我将这些字段添加为主键,并删除了过时的RatingID。

+0

请在您的答案中包含资源的相关信息。只有链接的答案可能会变得陈旧。 – Barmar 2015-02-06 20:37:51

+0

谢谢,我曾在收视率表上尝试过,但由于某种原因,它没有适当限制。 – seriestoo2 2015-02-06 20:41:08