Closed9
PostgreSQLで外部キー制約をON DELETE CASCADEにする方法
【前提】
現在の外部キー制約にはすべて、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にクローズされました