web-dev-qa-db-ja.com

Oracleで参照しているすべての外部キーへの主キー更新のカスケード

主キーを更新するときに、Oracleで参照しているすべての外部キーを更新することは可能ですか?

テーブル名と主キーを取得し、すべてのテーブルですべての外部キーを見つけ、それを新しい値で更新するこのようなプロシージャ

  PROCEDURE cascade_update_primary(
                          table_name IN VARCHAR2,
                          primary_column IN Number,
                          new_value IN Number);

OracleはON UPDATE CASCADEをサポートしていません。

2

DEFERRABLE外部キー制約:

create or replace procedure cascade_update_primary
(
  p_table_name in varchar2,
  p_old_value in number,
  p_new_value in number
)
as
  l_column_name varchar2(128 char);
begin
  select
    cc.column_name into l_column_name
  from
    user_cons_columns cc
    join user_constraints c on (c.constraint_name = cc.constraint_name)
  where
    c.constraint_type = 'P' and c.table_name = p_table_name
  ;

  execute immediate 'set constraints all deferred';

  execute immediate 'update "' || p_table_name || '" set "' || l_column_name || 
    '" = :B1 where "' || l_column_name || '" = :B2' using p_new_value, p_old_value;

  for c in (
    select
      cc2.table_name, cc2.column_name
    from
      user_cons_columns cc
      join user_constraints c on (c.constraint_name = cc.constraint_name)
      join user_constraints c2 on (c.constraint_name = c2.r_constraint_name)
      join user_cons_columns cc2 on (c2.constraint_name = cc2.constraint_name)
    where
      c.constraint_type = 'P' and c.table_name = p_table_name
      and cc.column_name = l_column_name
  )
  loop
    execute immediate 'update "' || c.table_name || '" set "' || c.column_name || 
      '" = :B1 where "' || l_column_name || '" = :B2' using p_new_value, p_old_value;
  end loop;
end;
/

の場合には NOT DEFERRABLE外部キー、一部変更あり:

  1. 新しいPK値で親行を挿入する
  2. 子テーブルを新しい値に更新する
  3. 古いPK値を持つ親行を削除します
4
Balazs Papp