当您在 Oracle 中删除附加了外键的主键约束然后重新启用主键时会发生啥?

Posted

技术标签:

【中文标题】当您在 Oracle 中删除附加了外键的主键约束然后重新启用主键时会发生啥?【英文标题】:What happens when you drop a primary key constraint that has a foreign key attached to it in Oracle and then re-enable the primary key?当您在 Oracle 中删除附加了外键的主键约束然后重新启用主键时会发生什么? 【发布时间】:2020-07-23 07:18:48 【问题描述】:

好吧,假设您有 2 张桌子,Table1Table2

Table1 的主键是Table2 的外键。如果你去掉Table1上的主键约束,然后用Alter Table命令重新启用它,Table2上的外键也会自动重新启用吗?

【问题讨论】:

不,引用已被破坏。您需要重置外键以获取对主键的新引用。看这里:***.com/questions/13629087/… mysql 中,你不能回滚 ddl 语句,所以我认为你的这个问题不是针对 mysql 的。 @RyffLe 是完全被摧毁还是只是被禁用?表回滚到原始状态后,我可以更改 Table2 并重新启用约束吗? 这是一个 Oracle 问题吗?在 Oracle 中不能回滚 DDL 它完全被破坏了。您需要 ALTER 表来恢复密钥 【参考方案1】:

让我们试试会发生什么。

首先创建表 t1 和 t2。

CREATE TABLE t1 (parent_id NUMBER);
Table created
CREATE TABLE t2 (child_id NUMBER);
Table created

然后创建 2 个约束

ALTER TABLE t1 ADD CONSTRAINT t1_pk PRIMARY KEY (parent_id) USING INDEX;
Table altered
ALTER TABLE t2 ADD CONSTRAINT t2_fk FOREIGN KEY (child_id) REFERENCES t1;
Table altered

现在查看字典并选择 2 个表的约束

SELECT c.CONSTRAINT_NAME, c.CONSTRAINT_TYPE, c.R_CONSTRAINT_NAME
FROM User_Constraints c WHERE c.TABLE_NAME IN ('T1', 'T2');
CONSTRAINT_NAME                CONSTRAINT_TYPE R_CONSTRAINT_NAME
------------------------------ --------------- ------------------------------
T1_PK                          P               
T2_FK                          R               T1_PK

我们看到 1 个主键 (P) 和 1 个外键 (R) 然后放下pk

ALTER TABLE t1 DROP CONSTRAINT t1_pk CASCADE;
Table altered

cascade 关键字指示 oracle 隐式删除所有引用要删除的 pk 的 fk 约束。如果没有级联,您将得到 ORA-02273:此唯一/主键被某些外键引用,并且 pk 不会被丢弃。

再次查看字典并选择 2 个表的约束

SELECT c.CONSTRAINT_NAME, c.CONSTRAINT_TYPE, c.R_CONSTRAINT_NAME
FROM User_Constraints c WHERE c.TABLE_NAME IN ('T1', 'T2');
CONSTRAINT_NAME                CONSTRAINT_TYPE R_CONSTRAINT_NAME
------------------------------ --------------- ------------------------------

没有行 - pk 和 fk 消失了。重新创建pk

ALTER TABLE t1 ADD CONSTRAINT t1_pk PRIMARY KEY (parent_id) USING INDEX;
Table altered

看看字典

SELECT c.CONSTRAINT_NAME, c.CONSTRAINT_TYPE, c.R_CONSTRAINT_NAME
FROM User_Constraints c WHERE c.TABLE_NAME IN ('T1', 'T2');
CONSTRAINT_NAME                CONSTRAINT_TYPE R_CONSTRAINT_NAME
------------------------------ --------------- ------------------------------
T1_PK                          P               

仅创建 pk。清理测试用例

DROP TABLE t2;
Table dropped
DROP TABLE t1;
Table dropped

【讨论】:

【参考方案2】:

让我们根据您的要求制作一个测试用例。我希望我正确理解了前提:

我有一个表 MY_PK,在 C1 列上有一个主键 我有一个表 MY_FK,其中包含 C1 列上的主键,它也是表 MY_PK 中 C1 列的外键。 您想禁用或删除表 MY_FK 中的主键以查看 FOREIGN KEY 会发生什么。

我们来玩吧:

SQL> create table my_pk ( c1 number primary key , c2 number );

Table created.

SQL> create table my_fk ( c1 number primary key , c2 number, constraint my_fk_constraint foreign key (c1) references my_pk (c1) ) ;

Table created.

SQL>  select table_name, constraint_name, constraint_type, status from dba_constraints where table_name in ( 'MY_FK' , 'MY_PK' ) and owner = 'MYOWNER' ;

TABLE_NAME                     CONSTRAINT_NAME                C STATUS
------------------------------ ------------------------------ - --------
MY_PK                          SYS_C00141013                  P ENABLED
MY_FK                          SYS_C00141016                  P ENABLED
MY_FK                          MY_FK_CONSTRAINT               R ENABLED

那么,按照你的要求去做吧:

禁用表 MY_FK 中的主键,它也是表 MY_PK 的外键

SQL> alter table my_fk disable primary key ;

Table altered.

SQL>  select table_name, constraint_name, constraint_type, status from dba_constraints where table_name in ( 'MY_FK' , 'MY_PK' ) and owner = 'MY_OWNER';

TABLE_NAME                     CONSTRAINT_NAME                C STATUS
------------------------------ ------------------------------ - --------
MY_PK                          SYS_C00141013                  P ENABLED
MY_FK                          SYS_C00141016                  P DISABLED
MY_FK                          MY_FK_CONSTRAINT               R ENABLED

让我们评估是否仍然强制执行外键,即使 pk 被禁用。您可以在上面看到 FK 在字典中显示为 ENABLED。

SQL> insert into my_pk values ( 1 , 1 );

1 row created.

SQL> commit;

Commit complete.

SQL> insert into my_fk values ( 2, 1 );
insert into my_fk values ( 2, 1 )
*
ERROR at line 1:
ORA-02291: integrity constraint (MYOWNER.MY_FK_CONSTRAINT) violated - parent
key not found

虽然 PK 已禁用,但仍强制执行外键,您仍可以根据需要插入重复项

SQL> insert into my_fk values ( 1 , 1 );

1 row created.

SQL> rollback;

Rollback complete.

SQL>

我们重新启用表 MY_FK 中的 PK

SQL> alter table my_fk enable primary key ;

Table altered.

SQL>  select table_name, constraint_name, constraint_type, status from dba_constraints where table_name in ( 'MY_FK' , 'MY_PK' ) ;

TABLE_NAME                     CONSTRAINT_NAME                C STATUS
------------------------------ ------------------------------ - --------
MY_PK                          SYS_C00141013                  P ENABLED
MY_FK                          SYS_C00141016                  P ENABLED
MY_FK                          MY_FK_CONSTRAINT               R ENABLED

删除表 MY_FK 中的主键,这也是 MY_PK 的外键

SQL> alter table my_fk drop primary key ;

Table altered.

SQL> select table_name, constraint_name, constraint_type, status from dba_constraints 
where table_name in ( 'MY_FK' , 'MY_PK' ) ;

TABLE_NAME                     CONSTRAINT_NAME                C STATUS
------------------------------ ------------------------------ - --------
MY_PK                          SYS_C00141013                  P ENABLED
MY_FK                          MY_FK_CONSTRAINT               R ENABLED

SQL> insert into my_pk values ( 2 , 2 );

1 row created.

SQL> select * from my_pk ;

        C1         C2
---------- ----------
         1          1
         2          2

SQL> insert into my_fk values ( 2 ,2 );

1 row created.

SQL> select * from my_fk ;

        C1         C2
---------- ----------
         1          1
         2          2

SQL> insert into my_fk values ( 3 , 3 );
insert into my_fk values ( 3 , 3 )
*
ERROR at line 1:
ORA-02291: integrity constraint (MYOWNER.MY_FK_CONSTRAINT) violated - parent
key not found

因此,无论是禁用主键约束还是删除表 MY_FK 中的主键约束,外键仍然被强制执行。显然,您可以在禁用主键的同时向表中添加重复项。我没有在我的测试用例中使用选项 CASCADE,它改变了另一个答案中提供的场景。

【讨论】:

以上是关于当您在 Oracle 中删除附加了外键的主键约束然后重新启用主键时会发生啥?的主要内容,如果未能解决你的问题,请参考以下文章

oracle 查询外键的名称

主键和外键的作用

mysql为啥被设了外键的表还能被删掉?

oracle中外键的作用

oracle 外键 删除

SQL中怎么修改主键里的属性这个主键和另一个表有外键约束