【问题标题】:Change primary key value in Oracle在 Oracle 中更改主键值
【发布时间】:2011-02-15 17:23:50
【问题描述】:

有没有办法改变另一个表作为外键引用的主键的值?

【问题讨论】:

    标签: database oracle foreign-keys primary-key


    【解决方案1】:

    另一种更简单的方法是插入新行并删除旧行。 (在删除之前更新其他表中的任何引用行)

    【讨论】:

      【解决方案2】:

      如果您要这样做,则没有内置的 UPDATE CASCADE。您需要执行诸如禁用任何 FK 约束之类的操作;运行更新语句;重新启用约束。

      请注意,更新主键(通常总是)是个坏主意。

      【讨论】:

        【解决方案3】:

        您需要在更改主键值之前禁用外键约束,然后再重新启用它们。

        如果您确实想实现“更新级联”功能,请参阅Tom Kyte's Update Cascade package

        【讨论】:

          【解决方案4】:

          如果您只想交换密钥(这也是更改的子集,因此它可能仍然是您问题的答案),即使没有禁用约束也是可能的。我在这里写了一个例子: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)
          

          【讨论】:

            【解决方案5】:

            是的,有一种方法可以在 Oracle 中进行级联更新,即使在事务中也是如此(这不适用于启用/禁用约束的选项)。但是,您必须自己实现它。可以通过更新前/更新后触发器来完成。

            这是可能的,因为触发器是在检查任何约束之前执行的。 (嗯,至少在 Oracle 11.2 中是这样。还没有对照 12.1 进行检查,但老实说,我相信它没有改变。)

            无论如何,如前所述,更新主键通常是个坏主意。

            【讨论】:

              【解决方案6】:

              原则是禁用约束,根据键运行 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'

              【讨论】:

                【解决方案7】:

                您可以做到这一点的另一种方法是更改​​外键约束,以便将约束的验证推迟到您提交之前 - 即 Oracle 不是逐个语句验证约束,而是按事务执行-交易。

                请注意,您不能通过“alter table”语句执行此操作,但您可以删除并重新创建可延迟的外键约束,即:

                alter table <table name> drop constraint <FK constraint name>;
                alter table <table name> add constraint <FK constraint name> foreign key .... initially deferrable;
                

                完成此操作后,只需按照您喜欢的任何顺序更新表格,然后提交 - 此时,任一:

                1. 您的所有 FK 约束都已满足,并且大家都很开心;或
                2. 您在某处违反了 FK 约束 - 您将收到错误,您必须修复数据并提交或回滚。

                请注意,此功能非常安全,因为 Oracle 不允许脏读,因此他们只会在您提交后才能看到更新的效果。因此,从其他所有会话的角度来看,参照完整性似乎得到了保留。

                此外,这是一次性更改,因此您无需在每次要更新主键时都执行 DDL。

                【讨论】:

                  猜你喜欢
                  • 1970-01-01
                  • 2015-09-10
                  • 1970-01-01
                  • 2020-09-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  相关资源
                  最近更新 更多