外部キーを含む行を削除したいのですが、次のようなことをしようとすると:
DELETE FROM osoby WHERE id_osoby='1'
私はこの声明を受け取ります:
エラー:テーブル "osoby"の更新または削除は、テーブル "kontakty"の外部キー制約 "kontakty_ibfk_1"に違反しています詳細:キー(id_osoby)=(1)は、まだテーブル "kontakty"から参照されています。
これらの行を削除するにはどうすればよいですか?
これを自動化するには、ON DELETE CASCADE
を使用して外部キー制約を定義できます。
引用 外部キー制約のマニュアル :
CASCADE
は、参照されている行が削除されたときに、それを参照している行も自動的に削除されることを指定します。
現在のFK定義を次のように検索します。
SELECT pg_get_constraintdef(oid) AS constraint_def
FROM pg_constraint
WHERE conrelid = 'public.kontakty'::regclass -- assuming pubic schema
AND conname = 'kontakty_ibfk_1';
次に、次のようなステートメントでON DELETE ...
部分をON DELETE CASCADE
に追加または変更します(他のすべてをそのまま保持)。
ALTER TABLE kontakty
DROP CONSTRAINT kontakty_ibfk_1
, ADD CONSTRAINT kontakty_ibfk_1
FOREIGN KEY (id_osoby) REFERENCES osoby (id_osoby) ON DELETE CASCADE;
ALTER CONSTRAINT
構文がないため、単一のALTER TABLE
ステートメントで制約を削除して再作成します。これにより、同時書き込みアクセスの競合状態を回避できます。
もちろん、そうするための特権が必要です。操作は、ACCESS EXCLUSIVE
テーブルのロックkontakty
と、_SHARE ROW EXCLUSIVE
テーブルのロックosoby
を取ります。
テーブルをALTER
できない場合、手動(1回)またはトリガーBEFORE DELETE
(毎回)で削除することが残りのオプションです。
外部キーがまだ別のテーブルを参照している場合は、外部キーを削除できません。最初に参照を削除します
delete from kontakty
where id_osoby = 1;
DELETE FROM osoby
WHERE id_osoby = 1;
これを一般的な解決策としてお勧めするべきではありませんが、本番環境またはアクティブに使用されていないデータベースの行を1回限り削除する場合は、問題のテーブルのトリガーを一時的に無効にできる場合があります。
私の場合、開発モードで、外部キーを介して相互に参照するテーブルがいくつかあります。したがって、コンテンツを削除することは、あるテーブルからすべての行を他のテーブルよりも前に削除するほど簡単ではありません。だから、私にとっては、次のようにコンテンツを削除してもうまくいきました:
ALTER TABLE table1 DISABLE TRIGGER ALL;
ALTER TABLE table2 DISABLE TRIGGER ALL;
DELETE FROM table1;
DELETE FROM table2;
ALTER TABLE table1 ENABLE TRIGGER ALL;
ALTER TABLE table2 ENABLE TRIGGER ALL;
もちろん、データベースの整合性が損なわれないように注意して、必要に応じてWHERE句を追加できる必要があります。
http://www.openscope.net/2012/08/23/subverting-foreign-key-constraints-in-postgres-or-mysql/ に関連する良い議論があります。
この質問が尋ねられてからしばらく経ちましたが、希望は助けになります。 db構造を変更または変更できないため、これを行うことができます。 postgresql docs に従います。
TRUNCATE-テーブルまたはテーブルのセットを空にします。
TRUNCATE [ TABLE ] [ ONLY ] name [ * ] [, ... ]
[ RESTART IDENTITY | CONTINUE IDENTITY ] [ CASCADE | RESTRICT ]
説明
TRUNCATEは、テーブルのセットからすべての行をすばやく削除します。各テーブルでの非修飾DELETEと同じ効果がありますが、実際にはテーブルをスキャンしないため、高速です。さらに、後続のVACUUM操作を必要とせずに、すぐにディスク領域を再利用します。これは、大きなテーブルで最も役立ちます。
テーブルothertableを切り捨て、外部キー制約を介してothertableを参照するテーブルにカスケードします。
TRUNCATE othertable CASCADE;
同じで、関連するシーケンスジェネレータもリセットします。
TRUNCATE bigtable, fattable RESTART IDENTITY;
関連するシーケンスジェネレータを切り捨ててリセットします。
TRUNCATE revinfo RESTART IDENTITY CASCADE ;
テーブルkontakty
には、削除するosoby
の行を参照する行があることを意味します。最初にその行を削除するか、テーブル間のリレーションに対してカスケード削除を設定してください。
ポウォゼニア!