我有一个书籍表,存储书籍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)
);
答案 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
行具有BookID
和CustomerID
的相同组合,您需要在UNIQUE
表上添加Rating
个约束,并将其命名为列。或者,您可以为Rating
表提供由这些列组成的复合主键。无论哪种方式,您都会有单独的约束,一个在引用表中建立这些列的唯一性,另一个约束它们到出现在Buys
表中的对。