【问题标题】:There are no primary or candidate keys in the referenced table ' ' that match the referencing column list in the foreign key被引用表“ ”中没有与外键中的引用列列表匹配的主键或候选键
【发布时间】:2020-10-15 19:45:43
【问题描述】:

好吧,我用谷歌搜索,显然发现了无穷无尽的结果,但没有一个是有帮助的。

错误似乎是不言自明的......但我看不出在这种情况下我做错了什么:

    CREATE TABLE Contrat
(ID_contrat int identity(1,1),
ID_client int,
code_contrat int,
date_début date,
date_fin date,
status_contrat varchar(20),
Totalité int,
montant_mensuel int,
CONSTRAINT PK_composed2 primary key(ID_contrat,ID_client,code_contrat),
CONSTRAINT FK_3 foreign key(code_contrat) references type_contract(code_type_contract) ON DELETE CASCADE,
CONSTRAINT FK_4 foreign key(ID_Client) references Clients(ID_Client) ON DELETE CASCADE
)



CREATE TABLE FonctionContract
(ID_FonctionContract int identity(1,1),
ID_contract int,
ID_fonction int,
nombre int,
prix_unitaire numeric(16,2),
Constraint PK_composed primary key(ID_fonctionContract, ID_Contract, ID_Fonction),
Constraint FK_11 foreign key(ID_contract) references Contrat(ID_contrat) ON DELETE CASCADE,
Constraint FK_2 foreign key(ID_Fonction) references Fonction(ID_fonction) ON DELETE CASCADE
)

错误发生在最后一行 (FK_11) 的前面。 一些结果表明我也应该做一个组合外键,但我不知道当我有 ID_FonctionContract 没有被链接到任何地方时。

【问题讨论】:

  • Y我们的主键是(ID_contrat,ID_client,code_contrat) 而不是ID_contratFOREIGN KEY 必须引用这些列的所有。错误实际上是在告诉你问题所在。
  • 所以你是说问题实际上来自第一个表而不是第二个?因为尽管听起来很奇怪,但第一张桌子可以正常工作。我只在第二张桌子上有错误。
  • 不,我是说您正在创建的 FOREIGN KEY 正在尝试引用由 ID_contrat 组成的 UNIQUE INDEXPRIMARY KEYContrat;那是不存在的。唯一的UNIQUE INDEXPRIMARY KEYContrat 位于ID_contrat,ID_client,code_contrat 列上,因此它不适用于仅引用其中一个列的键。
  • ID_fonctionContract 只是表的唯一标识符,我为什么要在某个地方引用它?
  • ID_fonctionContract 是表中的主键FonctionContract;与这里的问题无关。

标签: sql sql-server


【解决方案1】:

外键约束的每个值都需要准确引用目标表的一行,DBMS 需要能够根据表定义来保证这一点。

虽然 ID_contrat 列被定义为自增列,但它不限于唯一,因为您在 Contrat 表上定义了一个多列主键。因此,DBMS 表示您提议的外键中的单个 ID_contrat 可能会匹配 Contrat 表中的多行,这是不允许的。 (这似乎令人惊讶,因为可能知道它只会匹配一个,但 DBMS 不会!)

您需要做以下两件事之一:

  • 跨多个列定义外键,使其匹配多个列,保证在另一个表上是唯一的;这将要求您拥有 FonctionContrat 表中的所有三列(ID_contrat、ID_client 和 code_contrat)
  • 通过更改主键定义或在 ID_contrat 列上添加额外的唯一约束,调整 Contrat 表的定义以表明 ID_contrat 实际上在所有行中都是唯一的

我怀疑第二个选项在这里是合适的:使用自动增量列然后在其中插入重复项是相当不寻常的。

您可能想要的是两个不同的唯一约束/索引:一个在 ID_contrat 上,另一个在 ID_client 和 code_contrat 的组合上。其中只有一个可以标记为主键,另一个可以是唯一索引,在实践中具有大部分相同的功能;任何一个都可以标记为“集群”,这会告诉 SQL Server 根据该列对表进行物理布局。

【讨论】:

  • 你是说主键和唯一键不是一回事吗?
  • 还有第三个选项,在Contrat.ID_contrat上创建UNIQUE INDEX
  • @P.Salmon 从技术上讲,它们并不相同——一个表总是只有一个主键,但可以有任意数量的其他“候选键”,这些“候选键”可以用唯一约束或唯一索引来定义.在实践中,我没有遇到任何将主键与任何其他唯一键区别对待的情况。
  • @Larnu 这就是我所说的“添加或调整”的意思;我将对其进行编辑以使其更加明确。
猜你喜欢
  • 1970-01-01
  • 2013-07-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-07-25
  • 1970-01-01
  • 2023-03-05
相关资源
最近更新 更多