2015-02-06 111 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