当您没有所有列但可以通过另一个外键获取它们时,如何添加引用复合主键的外键?
How to add a foreign key referencing a composite primary key when you don't have all the columns, but can get them via another foreign key?
我有以下 tables:
create table AAA
(
AAA_ID NUMBER
);
alter table AAA
add constraint AAA_PK
primary key (AAA_ID);
create table BBB
(
BBB_ID NUMBER,
AAA_ID NUMBER
);
alter table BBB
add constraint BBB_PK
primary key (BBB_ID, AAA_ID); --IMPORTANT
alter table BBB
add constraint BBB_FK_01
foreign key (AAA_ID)
references AAA (AAA_ID);
create table CCC
(
CCC_ID NUMBER,
AAA_ID NUMBER
);
alter table CCC
add constraint CCC_PK
primary key (CCC_ID); --IMPORTANT
alter table CCC
add constraint CCC_FK_01
foreign key (AAA_ID)
references AAA (AAA_ID);
create table CCC_BBB
(
CCC_ID NUMBER,
CCC_BBB_ID NUMBER,
BBB_ID NUMBER
);
alter table CCC_BBB
add constraint CCC_BBB_PK
primary key (CCC_ID, CCC_BBB_ID);
alter table CCC_BBB
add constraint CCC_BBB_FK_01
foreign key (CCC_ID)
references CCC (CCC_ID);
我想在引用 BBB
的 CCC_BBB
中添加一个外键约束。 BBB_ID
直接出现在 CCC_BBB
中,但没有 AAA_ID
。但是,AAA_ID
出现在 CCC
中,它被 CCC_BBB_FK_01
引用。是否可以在 SQL?
中表达此约束
我更喜欢符合标准的解决方案,但也欢迎特定于 Oracle 的解决方案。
编辑。我被要求澄清现实世界的问题是什么,所以这是我的尝试(我不想在这里讨论真正的问题领域):
AAA 是一个过程。
BBB 是一个过程步骤。多个进程具有名称相似但含义不同的步骤,因此 table 具有复合键。
CCC 是一个流程实例。他们的 ID 是唯一的,所以 table 没有复合 PK。
CCC_BBB 是在特定实例中采取的步骤列表。
我需要确保流程实例的步骤列表仅包括该流程允许的那些步骤。
您的问题似乎源于复合键应用不周。
让我们先从技术 non-composite 键开始。我稍微重命名了 table 和列名以增强可读性。主键是粗体。
- A (A_ID, col1, col2, ...)
- AB (AB_ID, A_ID, col1, col2, ...)
- AC (AC_ID, A_ID, col1, col2, ...)
- ABC (ABC_ID, AC_ID, AB_ID, col1, col2, ...)
这里有你描述的情况:AC和AB对A是children,ABC对AB和AC都是child,但是DBMS不能保证BC包含B和C 都属于同一个 A。这是纯基于 ID 的数据库设计中的一个 well-known 缺点;它无法保证 table 层次结构的一致性。
现在与复合键相同(这在自然键中很常见,但也适用于技术 ID):
- A (A_ID, col1, col2, ...)
- AB (A_ID, B_ID, col1, col2, ...)
- AC (A_ID, C_ID, col1, col2, ...)
- ABC (A_ID, B_ID, C_ID, col1, col2, ...)
这里保证了一致性,因为完整的parent键总是主键的一部分。
你正在做的是混合。您正在将复合键应用于最后一个 table,但在所有 parent table 中您都没有,所以为时已晚。您使用了 non-composite ID 概念并遇到了它的一致性问题。
- A (A_ID, col1, col2, ...)
- AB (AB_ID, A_ID, col1, col2, ...)
- AC (AC_ID, A_ID, col1, col2, ...)
- ABC (AC_ID, ACSUB_ID, AB_ID, col1, col2, ...)
您可以使用物化视图连接两个 table,然后将外键添加到此:
CREATE MATERIALIZED VIEW LOG ON CCC_BBB
WITH SEQUENCE, ROWID(CCC_ID,CCC_BBB_ID,BBB_ID)
INCLUDING NEW VALUES;
CREATE MATERIALIZED VIEW CCC_BBB_MV
BUILD IMMEDIATE
REFRESH FAST ON COMMIT
AS SELECT CCC_ID,
CCC_BBB_ID,
BBB_ID,
AAA_ID
FROM CCC_BBB b
INNER JOIN
CCC c
ON ( b.CCC_ID = c.CCC_ID );
ALTER TABLE CCC_BBB_MV ADD CONSTRAINT ccc_bbb_mv__fk
FOREIGN KEY ( AAA_ID, BBB_ID ) REFERENCES BBB ( AAA_ID, BBB_ID );
(以上代码未经测试,但应说明解决方案)
虽然它可能有效,但有点麻烦,您将使用更少的存储空间 space 将 AAA_ID
添加到您的 CCC_BBB
table。
我有以下 tables:
create table AAA
(
AAA_ID NUMBER
);
alter table AAA
add constraint AAA_PK
primary key (AAA_ID);
create table BBB
(
BBB_ID NUMBER,
AAA_ID NUMBER
);
alter table BBB
add constraint BBB_PK
primary key (BBB_ID, AAA_ID); --IMPORTANT
alter table BBB
add constraint BBB_FK_01
foreign key (AAA_ID)
references AAA (AAA_ID);
create table CCC
(
CCC_ID NUMBER,
AAA_ID NUMBER
);
alter table CCC
add constraint CCC_PK
primary key (CCC_ID); --IMPORTANT
alter table CCC
add constraint CCC_FK_01
foreign key (AAA_ID)
references AAA (AAA_ID);
create table CCC_BBB
(
CCC_ID NUMBER,
CCC_BBB_ID NUMBER,
BBB_ID NUMBER
);
alter table CCC_BBB
add constraint CCC_BBB_PK
primary key (CCC_ID, CCC_BBB_ID);
alter table CCC_BBB
add constraint CCC_BBB_FK_01
foreign key (CCC_ID)
references CCC (CCC_ID);
我想在引用 BBB
的 CCC_BBB
中添加一个外键约束。 BBB_ID
直接出现在 CCC_BBB
中,但没有 AAA_ID
。但是,AAA_ID
出现在 CCC
中,它被 CCC_BBB_FK_01
引用。是否可以在 SQL?
我更喜欢符合标准的解决方案,但也欢迎特定于 Oracle 的解决方案。
编辑。我被要求澄清现实世界的问题是什么,所以这是我的尝试(我不想在这里讨论真正的问题领域):
AAA 是一个过程。 BBB 是一个过程步骤。多个进程具有名称相似但含义不同的步骤,因此 table 具有复合键。 CCC 是一个流程实例。他们的 ID 是唯一的,所以 table 没有复合 PK。 CCC_BBB 是在特定实例中采取的步骤列表。
我需要确保流程实例的步骤列表仅包括该流程允许的那些步骤。
您的问题似乎源于复合键应用不周。
让我们先从技术 non-composite 键开始。我稍微重命名了 table 和列名以增强可读性。主键是粗体。
- A (A_ID, col1, col2, ...)
- AB (AB_ID, A_ID, col1, col2, ...)
- AC (AC_ID, A_ID, col1, col2, ...)
- ABC (ABC_ID, AC_ID, AB_ID, col1, col2, ...)
这里有你描述的情况:AC和AB对A是children,ABC对AB和AC都是child,但是DBMS不能保证BC包含B和C 都属于同一个 A。这是纯基于 ID 的数据库设计中的一个 well-known 缺点;它无法保证 table 层次结构的一致性。
现在与复合键相同(这在自然键中很常见,但也适用于技术 ID):
- A (A_ID, col1, col2, ...)
- AB (A_ID, B_ID, col1, col2, ...)
- AC (A_ID, C_ID, col1, col2, ...)
- ABC (A_ID, B_ID, C_ID, col1, col2, ...)
这里保证了一致性,因为完整的parent键总是主键的一部分。
你正在做的是混合。您正在将复合键应用于最后一个 table,但在所有 parent table 中您都没有,所以为时已晚。您使用了 non-composite ID 概念并遇到了它的一致性问题。
- A (A_ID, col1, col2, ...)
- AB (AB_ID, A_ID, col1, col2, ...)
- AC (AC_ID, A_ID, col1, col2, ...)
- ABC (AC_ID, ACSUB_ID, AB_ID, col1, col2, ...)
您可以使用物化视图连接两个 table,然后将外键添加到此:
CREATE MATERIALIZED VIEW LOG ON CCC_BBB
WITH SEQUENCE, ROWID(CCC_ID,CCC_BBB_ID,BBB_ID)
INCLUDING NEW VALUES;
CREATE MATERIALIZED VIEW CCC_BBB_MV
BUILD IMMEDIATE
REFRESH FAST ON COMMIT
AS SELECT CCC_ID,
CCC_BBB_ID,
BBB_ID,
AAA_ID
FROM CCC_BBB b
INNER JOIN
CCC c
ON ( b.CCC_ID = c.CCC_ID );
ALTER TABLE CCC_BBB_MV ADD CONSTRAINT ccc_bbb_mv__fk
FOREIGN KEY ( AAA_ID, BBB_ID ) REFERENCES BBB ( AAA_ID, BBB_ID );
(以上代码未经测试,但应说明解决方案)
虽然它可能有效,但有点麻烦,您将使用更少的存储空间 space 将 AAA_ID
添加到您的 CCC_BBB
table。