问题描述
我遇到了一个问题,我无法创建一些表,因为它们的外键“格式不正确”。我不知道为什么会出现此错误,因为键的类型相同且名称唯一。代码非常简单:
CREATE TABLE Vehicle(
vin VARCHAR(25),ID VARCHAR(20),make VARCHAR(20),model VARCHAR(20),year_ VARCHAR(20),condition_ VARCHAR(20),PRIMARY KEY(vin,ID),FOREIGN KEY(ID) REFERENCES Listing(CarID)
);
CREATE TABLE Listing(
CarID VARCHAR(20),state_ VARCHAR(20),price INT(10),url VARCHAR(50),PRIMARY KEY(CarID),FOREIGN KEY(CarID) REFERENCES Vehicle(ID)
);
解决方法
如果 Vehicle 的主键是 (vin,ID)
,那么引用它的外键也必须有两列,顺序相同,数据类型相同。
但在您的情况下,您的 Listing 表没有 vin
列,因此它无法引用 Vehicle 的主键。
Listing 引用 Vehicle 的部分主键意味着什么?不能保证在 Vehicle 中只存在具有给定值 ID
的一行。它可以有多行具有相同的 ID
和不同的 vin
值。因此,Listing 可能是多个车辆的子代,这可能没有意义。
所以你必须:
-
在列表中添加一个
vin
列,这样它的外键就可以通过它的主键(两列)精确引用一行。 -
修改 Vehicle 表,使
ID
单独成为其主键。
更新:
我刚刚注意到您在两个表中似乎都有外键。这通常不需要。当我考虑您要建模的内容时,我猜列表有一个或多个车辆,对吗?所以 Vehicle 应该引用它的父 Listing。但是 Listing 不需要引用 Vehicle。
所以以下工作:
首先创建父表,因为在父表存在之前你不能做外键。在您的情况下,Listing 是父表。
CREATE TABLE Listing(
CarID VARCHAR(20),state_ VARCHAR(20),price INT(10),url VARCHAR(50),PRIMARY KEY(CarID)
);
然后创建子表,使用引用其父表的外键。
CREATE TABLE Vehicle(
vin VARCHAR(25),ID VARCHAR(20),make VARCHAR(20),model VARCHAR(20),year_ VARCHAR(20),condition_ VARCHAR(20),PRIMARY KEY(vin,ID),FOREIGN KEY(ID) REFERENCES Listing(CarID)
);
我在 MySQL 5.7.27 上测试过。
,这是正确的方法:
CREATE TABLE Vehicle(
vin VARCHAR(25),ID)
);
CREATE TABLE Listing(
CarVin VARCHAR(25),CarID VARCHAR(20),PRIMARY KEY(CarVin,CarID),FOREIGN KEY(CarVin,CarID) REFERENCES Vehicle(vin,ID)
);
在您的数据模型中有一个列表和车辆。
车辆可以在列表中(也可以不在列表中)。 Listing 有 n 辆车(所以你有一个 1 到 n 的关系)。
Listing 中的每一行都有一个车辆的引用,因此它需要车辆主键字段(或一些唯一字段)来引用它(车辆主键由“vin”和“ID”字段复合而成)。
所以Listing中的主键也应该由“vin”和“ID”复合而成,就像Vehicle的表一样。 使用整数自增字段作为每个表的主键是一个好习惯。
您需要在表 Listing 中添加“CarVin”字段,然后 Listing 中的外键将为 FOREIGN KEY(CarVin,ID)
。
当您插入 Listing 行时,外键将检查是否存在值为 CarVin 和 CarID 的车辆。
要在表 Vehicle 中添加外键,您应该禁用外键检查 (SET FOREIGN_KEY_CHECKS=0;
),直到创建表,因为表 Listing 尚不存在(如果您创建第一个表 Vehicle)。但我认为在这种情况下没有意义,至少您要确保所有车辆都在 Listing 表中。
要插入数据,您必须先插入车辆,然后将其添加到Listing表中(检查外键,至少直到最后禁用外键检查),否则外键检查将失败。
在@"Bill Karwin" 的模型中,您需要先插入 Listing 行,然后插入 Vehicle。
MySql foreign key constraint documentation,MySql中各个存储引擎对外键约束的实现方式不同。
两个表相互有外键约束:
SET FOREIGN_KEY_CHECKS=0;
CREATE TABLE Vehicle(
vin VARCHAR(25),FOREIGN KEY(vin,ID) REFERENCES Listing(CarVin,CarID)
);
CREATE TABLE Listing(
CarVin VARCHAR(25),ID)
);
SET FOREIGN_KEY_CHECKS = 1;