sql - 使用多个外键引用两列主键

标签 sql oracle key sqlplus

在Oracle中获取以下两个表:

Create Table A
( A int, B int, C int,
  Constraint pk_ab Primary Key(A, B),
  Unique (C)
);

Create Table B
( D int, E int, F int,
  Constraint fk_d Foreign Key (D) References A(A),
  Constraint fk_e Foreign Key (E) References A(B)
);

为什么这个语句不起作用?或者更具体地说,为什么它不起作用?我尝试创建这种类型的关系的原因是,将来我想删除 B.D,但保留关系 FK_E

我收到错误:

ORA-02270: no matching unique or primary key for this column-list

最佳答案

"Why doesn't this statement work? Or more specifically, why shouldn't it work? "

您已将 A 上的主键定义为两列 (A,B) 的组合。任何引用 PK_AB 的外键必须在数量上与这些列匹配。这是因为外键必须标识引用表中的单个行,该行拥有子表中的任何给定行。复合主键意味着 A.A 列可以包含重复值,A.B 列也可以包含重复值;只有 (A,B) 的排列是唯一的。因此,引用外键需要两列。

Create Table B
( D int, E int, F int,
  Constraint fk_de Foreign Key (D,E) References A(A,B)
);

"Since there are multiple PK's that table B references"

错了。 B 引用单个主键,该主键恰好包含多个列,

" say, in the future, I want to delete B.D, but keep the relation fk_e. "

这没有道理。可以这样想:D 不是 B 的属性,而是 B 通过依赖表 A 继承的属性。

避免这种情况的一种方法是使用代理(或合成)键。复合键通常是业务键,因此它们的列在业务上下文中有意义。有意义的列值的一个特征是它们可以更改,并且将此类更改级联到外键可能会很困惑。

实现代理键如下所示:

Create Table A
( id int not null, A int, B int, C int,
  Constraint pk_a Primary Key(ID),
  constraint uk_ab Unique (A,B)
);

Create Table B
( a_id int, F int,
  Constraint fk_n_a Foreign Key (A_ID) References A(ID)
);

当然,您可以使用您发布的架构来执行此操作,因为您已经对 A(C) 有单列约束。但是,我认为引用唯一约束而不是主键是不好的做法,即使这是允许的。我认为这部分是因为独特的约束通常强制执行业务键,因此意味着改变的潜力,但主要是因为引用主键只是行业标准。

关于sql - 使用多个外键引用两列主键,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14543846/

相关文章:

oracle - Rows在解释计划中表示什么?

python - 使用 Python 使用公钥和 cx_Oracle 进行身份验证

Android - 如何在用户按下主页按钮时退出应用程序?

sql - 创建包含具有静态信息的列的 View

sql-maven-plugin 按照 pom.xml 中列出的确切顺序执行文件

oracle - 从 Oracle 查询生成图表的选项

scala - Scala 中的多键映射

python - 如何识别/打印字典中具有最大值的键?

sql - 如何使用 SQL 查找表中的第一列和第一行

SQL- 查询以获取最大日期低于特定日期的行