有没有办法将另一个表引用的主键的值更改为外键?
答案 0 :(得分:6)
更简单的替代方法是插入新行并删除旧行。 (在执行删除之前更新其他表中的任何引用行)
答案 1 :(得分:4)
没有内置的UPDATE CASCADE,如果这就是你所追求的。您需要执行禁用任何FK约束的操作;运行UPDATE语句;重新启用约束。
请注意,更新主键(通常总是)是一个坏主意。
答案 2 :(得分:2)
您需要在更改主键值之前禁用外键约束,然后再重新启用它们。
如果您确实想要实现“更新级联”功能,请参阅Tom Kyte's Update Cascade package
答案 3 :(得分:1)
即使没有禁用约束也是可能的,如果您只想交换密钥(这也是更改的子集,因此它仍然可以回答您的问题)。我在这里写了一个例子:https://stackoverflow.com/a/26584576/1900739
update MY_TABLE t1
set t1.MY_KEY = (case t1.MY_KEY = 100 then 101 else 100 end)
where t1.MYKEY in (100, 101)
答案 4 :(得分:0)
是的,有一种方法可以在Oracle中进行级联更新,即使在事务中也是如此(对于启用/禁用约束的选项不适用)。但是,您必须自己实施。它可以通过之前/之后的行更新触发器来完成。
由于在检查任何约束之前执行触发器是可能的。 (好吧,至少在Oracle 11.2中这是真的.Haven对12.1进行了检查,但老实说我相信它没有改变。)
无论如何,如前所述,更新主键通常是一个坏主意。
答案 5 :(得分:0)
原则是禁用约束,根据键运行你的udates,然后重新启用约束。这是一个运行禁用脚本的脚本: (假设所有约束都在启动时启用)
生成脚本
SELECT 'alter table ' || uc.table_name|| ' disable constraint '|| uc.constraint_name|| ' ;'
FROM user_constraints uc inner join user_cons_columns ucc on uc.constraint_name = ucc.constraint_name where column_name = 'MYCOLUMN_USED_AS_FOREIGN_KEY' and constraint_type='R'
复制/粘贴生成的脚本并运行它
alter table MYTABLE1 disable constraint FK_MYTABLE1 ;
alter table MYTABLE2 disable constraint MYTABLE2 ;
alter table MYTABLE3 disable constraint FK3_MYTABLE3 ;
...
然后更新您的PK值:
update MYTABLE1 set MYFIELD= 'foo' where MYFIELD='bar';
update MYTABLE2 set MYFIELD= 'foo' where MYFIELD='bar';
update MYTABLE3 set MYFIELD= 'foo' where MYFIELD='bar';
commit;
生成启用约束脚本:
SELECT 'alter table ' || uc.table_name|| ' enable constraint '|| uc.constraint_name|| ' ;'
FROM user_constraints uc inner join user_cons_columns ucc on uc.constraint_name = ucc.constraint_name where column_name = 'MYCOLUMN_USED_AS_FOREIGN_KEY' and constraint_type='R'
答案 6 :(得分:0)
另一种方法是通过更改外键约束,以便约束的验证推迟到您提交 - 即代替Oracle验证约束语句,它将执行事务处理-transaction。
请注意,您无法通过“alter table”语句执行此操作,但您可以删除并重新创建可以延迟的外键约束,即:
alter table <table name> drop constraint <FK constraint name>;
alter table <table name> add constraint <FK constraint name> foreign key .... initially deferrable;
完成后,只需按照您喜欢的顺序更新表,然后提交 - 此时,可以:
请注意,此功能非常安全,因为Oracle不允许脏读,因此一旦提交,它们只会看到更新的效果。因此,从每个其他会话的角度来看,似乎都保留了引用完整性。
此外,这是一次性更改,因此每次要更新主键时都不需要执行DDL。