当您在 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 张桌子,Table1
和 Table2
。
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 中删除附加了外键的主键约束然后重新启用主键时会发生啥?的主要内容,如果未能解决你的问题,请参考以下文章