MySQL:使用外键创建一个表,该外键引用由外键组成的主键

时间:2015-02-06 20:28:48

标签: mysql database

我有一个书籍表,存储书籍ID和标题,作者等,一个客户表,其中包含客户ID(PK),客户名称,生日。然后是一个事务表,其中包括BookId和CustomerID作为外键。此事务表的主键是两个外键列。

现在的问题是我正在根据已发生的交易创建一个图书评级表(因此,客户无法评价他们不拥有的图书或同一本书两次。)。此表必须包含bookID,customerID和评级信息。我正在尝试约束表,以便每个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)
);

2 个答案:

答案 0 :(得分:0)

您可以创建http://dev.mysql.com/doc/refman/5.0/en/create-table-foreign-keys.html中记录的多列外键引用 这应该可以解决问题。

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

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和CustID上添加唯一约束,或将这些字段设置为主键。在上面的工作代码示例中,我已将这些字段添加为主键并删除了过时的RatingID。

答案 1 :(得分:0)

您的Rating表上已有一个外键,该外键应限制Rating行,每行对应Buys行。我认为问题必须与你的另一个目标有关,即顾客不能对同一本书进行两次评价。关于这一点,我猜你对外键有一个误解:它们必须在目标表上是唯一的,但它们在引用方面不一定是唯一的。

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