我有三张桌子:
CREATE TABLE Address (
ResidentID CHAR(5) NOT NULL,
Location varchar(255) NOT NULL,
KEY ResidentID(ResidentID)
);
CREATE TABLE Customer (
CustomerID CHAR(5) NOT NULL,
ContactName varchar(40) NOT NULL,
PRIMARY KEY (CustomerID)
);
CREATE TABLE Supplier (
SupplierID CHAR(5) NOT NULL,
SupplierName varchar(40) NOT NULL,
PRIMARY KEY (SupplierID)
);
我想使用外键将CustomerID和SupplierID存储在Address.ResidentID字段中:
ALTER TABLE Address ADD CONSTRAINT fk_CustomerID1 FOREIGN KEY(ResidentID) REFERENCES Customer(CustomerID);
ALTER TABLE Address ADD CONSTRAINT fk_SupplierID1 FOREIGN KEY(ResidentID) REFERENCES Supplier(SupplierID);
但第二个“ALTER TABLE”引发错误:关系已存在
有什么建议吗?
数据示例:
CustomerID ContactName
C0001 Den
SupplierID ContactName
S0001 John
So Address table should contains:
ResidentID Location
C0001 Alaska
S0001 Nevada
答案 0 :(得分:3)
您需要引用客户/供应商的地址(如果他们只有一个)或两个不同的列。
您在此SQLFiddle中看到的原因如果INSERT
引用了两个表,则无法Address
ResidentID
表中所需的列。您只能插入与Customer
和Supplier
的内容相匹配的行,但您想要一个无法以这种方式创建的OR连接。
(注意:在我的解决方案中,我假设地址是可选的。由于Tom指出in the comments可能不是您想要的或预期的。确保在第一个标记FK列解决方案为NOT NULL
如果您希望地址是强制性的,那么对于第二个地址则更复杂。那么您必须记住正确的插入顺序。)
或者:
CREATE TABLE Address (
AddressID CHAR(5) NOT NULL,
Location varchar(255) NOT NULL,
PRIMARY KEY (AddressID)
);
CREATE TABLE Customer (
CustomerID CHAR(5) NOT NULL,
AddressID CHAR(5),
ContactName varchar(40) NOT NULL,
PRIMARY KEY (CustomerID)
);
CREATE TABLE Supplier (
SupplierID CHAR(5) NOT NULL,
AddressID CHAR(5),
SupplierName varchar(40) NOT NULL,
PRIMARY KEY (SupplierID)
);
ALTER TABLE Customer ADD CONSTRAINT fk_AddressID_Cust FOREIGN KEY(AddressID) REFERENCES Address(AddressID);
ALTER TABLE Supplier ADD CONSTRAINT fk_AddressID_Supp FOREIGN KEY(AddressID) REFERENCES Address(AddressID);
或
CREATE TABLE Address (
CustomerID CHAR(5),
SupplierID CHAR(5),
Location varchar(255) NOT NULL,
PRIMARY KEY (CustomerID, SupplierID)
);
CREATE TABLE Customer (
CustomerID CHAR(5) NOT NULL,
ContactName varchar(40) NOT NULL,
PRIMARY KEY (CustomerID)
);
CREATE TABLE Supplier (
SupplierID CHAR(5) NOT NULL,
SupplierName varchar(40) NOT NULL,
PRIMARY KEY (SupplierID)
);
ALTER TABLE Address ADD CONSTRAINT fk_CustomerID1 FOREIGN KEY(CustomerID) REFERENCES Customer(CustomerID);
ALTER TABLE Address ADD CONSTRAINT fk_SupplierID1 FOREIGN KEY(SupplierId) REFERENCES Supplier(SupplierID);
答案 1 :(得分:-1)
你正在尝试的方法是(a)不可能和(b)即使有可能也不受欢迎。
最好的方法是拥有一个CustomerAddress表和一个SupplierAddress表,每个表都有一个匹配基表的FK;或者如果必须,还有一个具有适当约束的交叉引用表。
如果您拥有单个地址表的动机是代码重用,您仍然可以这样做......根据模板xxxAddress表设计来思考,该表设计可以引用任何基础xxx表。您可以编写将基表名称视为参数的非数据库代码,然后随着时间的推移添加更多基表,可以处理任意数量的xxxAddress表。
或者,如果您拥有单个地址表的动机是为了简化报告,您始终可以创建一个视图或存储过程,它返回所有此类表的并集+一个添加的字段,以指示每个地址行的基表。 / p>
Angelo我根据你的意见修改了一下---
Angelo,我在本地MySQL实例(不是SQLFiddle)中运行了示例代码并发现了错误。
我很惊讶(你每天都学到一些东西)MySQL确实允许在同一个字段上定义两个外键约束;但是当您尝试插入数据时,在尝试将FK指向Customer表时,我收到一条错误,指出外键约束未能引用Supplier表;对于试图将FK指向供应商表格的插入,反之亦然。
所以我修改后的声明是(a)可以在至少一些DBMS中创建一个头脑中的FK - 在MySQL,MS SQL Server和Oracle中验证 - 尽管(b)这只有在使用时才有意义外键可以通过多个表中的ID引用相同的逻辑实体(例如,以确保在所有必需的表中存在相应的记录); (c)如果用于引用主键不是同一逻辑实体的多个表,只有在相同的主键值碰巧存在于所有引用表中时才起作用,这可能导致微妙,困难发现错误。
换句话说,只有在供应商ID = 3时才尝试插入引用客户ID = 3的记录时,您的示例才有效,这在逻辑上是无关的。
所以我稍微修改了对OP的回答是,当外键引用不同的ENTITIES时,您尝试做的事情是不可能的(或逻辑上的),如客户和供应商的OP示例中所示。