私はこれらのテーブルを持っています:
出来事 (evt_id、evt_code、reg_id) 大きさ (mag_id、evt_id、value) 痕跡 (trace_id、pt_id) ポイント (pt_id、evt_id)
evt_id=1139
に関連するすべてのテーブルからすべての行を削除したい。
どうすればいいのですか?
スキーマを制御できる場合は、スキーマで カスケード削除 を使用します。
記事から(あなたの例のために翻訳されたより適切な部分)
CREATE TABLE point
(
pt_id integer PRIMARY KEY,
evt_id integer REFERENCES event ON DELETE CASCADE
)
カスケードを設定している場合、メインイベントテーブルから削除するだけで、他のすべてのテーブルは自動的にクリーンアップされます
それ以外の場合は、最初にすべての参照を削除してから、メインテーブルを削除する必要があります。データの一貫性を保つために、1つのトランザクションでこれを行う必要があります
BEGIN;
DELETE FROM trace WHERE EXISTS
(SELECT 1 FROM point WHERE evt_id = 1139 AND trace.pt_id = point.pt_id);
DELETE FROM point where evt_id = 1139;
DELETE FROM magnitude where evt_id = 1139;
DELETE FROM event where evt_id = 1139;
COMMIT;
あなたの質問の重要な要素は、テーブルtrace
からの削除だけです。 trace.pt_id
がpoint.pt_id
を参照していると想定しても安全だと思いますか?
foreign keyをON DELETE CASCADE
で定義し、テーブルtrace
を忘れます(既に @kevin )によって指摘された、または手動で行に依存することに注意する必要があります。
PostgreSQL9.1以降、 data-modifying CTEs :
BEGIN;
WITH x AS (
DELETE FROM point WHERE evt_id = 1139
RETURNING pt_id
)
DELETE FROM trace
USING x
WHERE trace.pt_id = x.pt_id;
DELETE FROM magnitude WHERE evt_id = 1139;
DELETE FROM event WHERE evt_id = 1139;
COMMIT;
DELETE FROM point
の RETURNING句 は、影響を受けるすべてのpt_id
を返します。これらは、trace
からすべての対応する行を削除するために使用されます。
concurrencyが問題であるかどうかは言及しませんでした。ある場合、およびevt_id = 1139
の行が別のテーブルから既に削除されている間に別のテーブルに存在する削除の間の短い時間ウィンドウで起こり得る結果を避けたい場合は、すべてをtransaction。
それが気にならない場合は、BEGIN
とCOMMIT
を無視してください。
deadlocksを回避するには、常に同じシーケンスのdeleteステートメントを(すべての同時トランザクションで)使用します。これにより、1つのトランザクションが1つのテーブルで削除を開始し、別のトランザクションが別のテーブルで削除されてから、それぞれが他のテーブルを待機するという状況を回避できます。
削除する行を階層として想定できる場合、ON DELETE CASCADE句を使用して関係のFOREIGN KEY制約を定義できます。上部の行を削除すると、カスケードしてすべて削除されます。
http://www.postgresql.org/docs/9.1/static/ddl-constraints.html#DDL-CONSTRAINTS-FK