Closed9

PostgreSQLで外部キー制約をON DELETE CASCADEにする方法

モイテリカモイテリカ

PostgreSQLで外部キー(FK)をすべて削除する方法より、

SELECT 'ALTER TABLE "'||nspname||'"."'||relname||'" DROP CONSTRAINT "'||conname||'";'
 FROM pg_constraint 
 INNER JOIN pg_class ON conrelid=pg_class.oid 
 INNER JOIN pg_namespace ON pg_namespace.oid=pg_class.relnamespace 
 WHERE contype='f' 
 ORDER BY CASE WHEN contype='f' THEN 0 ELSE 1 END,contype,nspname,relname,conname
モイテリカモイテリカ

↑の削除用ALTER文に加えて、下記の追加用ALTER文の結果をあらかじめ取っておく。
追加用ALTER文

SELECT
    'ALTER TABLE "' || 'public' || '".' || conrelid ::regclass || ' ADD CONSTRAINT ' || conname || ' FOREIGN KEY ('
     || a.attname || ') REFERENCES ' || confrelid ::regclass || ' (' || af.attname || ') ON DELETE CASCADE;'
     as al1
    , 'ALTER TABLE "' || 'public' || '".' || conrelid ::regclass || ' ADD CONSTRAINT ' || conname || ' FOREIGN KEY ('
     || a.attname || ') REFERENCES ' || confrelid ::regclass || ' (' || af.attname || ');' as al2 
FROM
    pg_constraint 
    INNER JOIN pg_attribute a 
        ON a.attrelid = pg_constraint.conrelid 
        and a.attnum = ANY (pg_constraint.conkey) 
    INNER JOIN pg_attribute af 
        ON af.attrelid = pg_constraint.confrelid 
        and af.attnum = ANY (pg_constraint.confkey) 
        AND af.attrelid = pg_constraint.confrelid 
WHERE
    contype = 'f';
モイテリカモイテリカ

ALTER DROPで外部キー制約を削除。
ALTER ADD ON DELETE CASCADEにして、目的のデータを削除。
ALTER DROPで外部キー制約を削除。
ALTER ADDで元に戻す。

モイテリカモイテリカ

免責事項:PostgreSQLに詳しくないので、間違いがあるかもです。

モイテリカモイテリカ

引用符付き識別子を使っているとエラーになるので、そこは微調整ください。

モイテリカモイテリカ

DROPしなくても、既存外部キーを変更できた気がしないでもないです……。

モイテリカモイテリカ

関係する外部キーが少ないなら、手動でそこだけON DELETE CASCADEにする方が賢いかもです。

モイテリカモイテリカ

外部キー制約が連鎖してた場合、途中で消した場合にどうなるかは未テスト。

このスクラップは2024/08/09にクローズされました