Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/mysql/59.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
MySQL中的一个字段和两个引用_Mysql_Foreign Keys - Fatal编程技术网

MySQL中的一个字段和两个引用

MySQL中的一个字段和两个引用,mysql,foreign-keys,Mysql,Foreign Keys,我有三张桌子: 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 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);
但第二个“altertable”引发了错误:关系已经存在

有什么建议吗

数据示例:

CustomerID  ContactName
C0001       Den

SupplierID  ContactName
S0001       John

So Address table should contains:

ResidentID  Location
C0001       Alaska
S0001       Nevada

您需要引用客户/供应商的地址(如果他们只有一个)或两个不同的列

如果
ResidentID
引用了这两个表,那么您在这里看到的原因是不能
将所需列插入
地址
表中。您只能插入与
Customer
Supplier
的内容相匹配的行,但您需要的是一个OR连接,而您无法以这种方式创建

(注意:在我的解决方案中,我假设地址是可选的。正如所指出的,这可能不是您想要的或期望的。请确保将第一个解决方案中的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);


你尝试的方法是(a)不可能的,(b)不可取的,即使它是可能的

最好的方法是有一个CustomerAddress表和一个SupplierAddress表,每个表都有一个到匹配基表的FK;或者,如果必须,可以使用具有适当约束的交叉引用表

如果您使用单个地址表的动机是代码重用,那么您仍然可以这样做。。。考虑一下可以引用任何基本xxx表的模板xxx地址表设计。您可以编写非数据库代码,将基表名称作为参数处理,然后随着时间的推移添加更多的基表,可以处理任意数量的xxxAddress表

或者,如果使用单个地址表的目的是简化报告,则始终可以创建一个视图或存储过程,该过程返回所有此类表的并集+一个添加的字段,以指示每个地址行的基表

Angelo根据您的评论,我对这篇文章做了一些修改--

Angelo,我在本地MySQL实例(不是SQLFiddle)中运行了您的示例代码,发现了一个错误

我很惊讶(你每天都会学到一些东西),MySQL允许在同一个字段上定义两个外键约束;但是,当您尝试插入数据时,当尝试将FK指向Customer表时,我得到一个错误,即外键约束无法引用Supplier表;对于试图将FK指向Supplier表的insert,反之亦然

因此,我的修订声明是:(a)至少可以在一些DBMS中创建hydra-headed FK——在MySQL、MS SQL Server和Oracle中进行验证——尽管(b)只有在外键可以通过ID跨多个表引用同一逻辑实体时才有意义(例如,确保在所有必需的表中都有相应的记录);以及(c)如果用于引用主键不是同一逻辑实体的多个表,则仅当碰巧在所有引用的表中都存在相同的主键值时才起作用,这可能会导致细微的、难以发现的错误

换句话说,您的示例在尝试插入引用Customer ID=3的记录时会起作用,前提是还有一个Supplier ID=3,这在逻辑上是不相关的


因此,我对OP稍加修改的回答是,你试图做的是不可能的(或合乎逻辑的)当外键指向不同的实体时,如客户和供应商的OP示例中所示。

我在本地运行此操作时,没有收到任何错误。只是为了澄清,您希望单个地址条目始终具有相应的客户和供应商条目吗?我认为客户可能有地址,也可能没有地址,而客户可能有地址或者可能不是供应商,这将允许您将地址和供应商与客户联系起来;地址似乎是一个奇怪的地方,将两者联系在一起。但是,如果目的是将地址与其中一个或另一个相关联,则应为每个地址添加不同的字段。@Sharique,我也测试了它,但也没有出现错误。有什么g在这个问题上是错误的。这个错误不是MySQL错误。但是当你试图为约束创建一个重复的名称时,它是PostgreSQL错误。我认为你混淆了你正在使用的RDBMS。@AngeloNeuschitzer,我刚刚灰色了MySQL 5.6.13源代码树,错误消息“relation…已经存在”不在源代码中。但如果您搜索“postgresql关系已存在”你会发现很多匹配项,包括一些关于StackOverflow的问题。因此OP可能会对MySQL实例使用phpMyAdmin,但这不是错误的来源。+1好建议,但我怀疑这不是OP问题的真正根源。我认为他使用的是两个不同的RDBMS实例,一个MySQL和一个PostgreSQL,以及he不清楚他将更改应用于哪一个。注意:a)由于第一个解决方案的FK列未定义为
notnull
,因此它不会强制C/s表行具有表行。b) 即使它们被设置为
非空
,也会强制每个C/S表行都有一个A表行,但反之亦然。c) 由于MySQL(顺便说一句,SQL Server也)强制PK列不为NULL,因此第二个解决方案实际上会实现一个“and”(除非添加了伪c和S表行,这仍然只会强制每个A表行都有c和S,而不是相反)。我认为OP需要“或”连接,并且a和C或S之间也需要1对1的关系。^或者更准确地说,我认为OP需要“XOR”连接,也需要1对1的关系,这样相应的行必须存在于“a和(C XOR S)”表中。这两种解决方案(即使添加了显式/隐式
notnull
和/或伪行)都没有完全实现该需求,尽管它们确实获得了很多clo
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);