2010-07-19 7 views
5

Ich möchte Zeilen aus zwei Tabellen löschen, die durch eine Reihe von schiebbaren Bedingungen voneinander abhängig sind. Um diesen Beitrag zu vereinfachen, habe ich ein einfaches DB-Schema gespottet.PostgreSQL 'Deferrable Delete' trifft immer noch die Einschränkung auf Löschen

Ich hoffe, Einträge aus einer Tabelle, "delete_from_me", in einer SQL-Transaktion/DB Patch zu entfernen. Der Catch ist, ich möchte basierend auf einer Auswahl aus einer zweiten Tabelle 'Constraining_Table' löschen, bevor ich den Link selbst verliere.

Hier ist eine Beschreibung der beiden Tabellen:

tab-quarantine=> \d delete_from_me 
     Table "public.delete_from_me" 
    Column |  Type  | Modifiers 
-----------+-------------------+----------- 
id  | character varying | not null 
extension | character varying | not null 
Indexes: 
    "delete_from_me_pkey" PRIMARY KEY, btree (id) 

tab-quarantine=> \d constraining_table 
    Table "public.constraining_table" 
Column |  Type  | Modifiers 
--------+-------------------+----------- 
image | character varying | not null 
type | character varying | not null 
Foreign-key constraints: 
    "constraining_table_image_fkey" FOREIGN KEY (image) REFERENCES delete_from_me(id) 
     ON UPDATE CASCADE 
     ON DELETE RESTRICT DEFERRABLE 

Hier einige Beispieldaten ich dort nur blatted:

tab-quarantine=> SELECT * FROM delete_from_me; 
    id  | extension 
------------+----------- 
12345abcde | png 
(1 row) 

tab-quarantine=> SELECT * FROM constraining_table; 
    image | type 
------------+---------- 
12345abcde | select_me 
(1 row) 

Und hier geht meine Transaktion:

BEGIN; 
\set ON_ERROR_STOP 1 
SET CONSTRAINTS ALL DEFERRED; 
DELETE FROM delete_from_me WHERE id IN (
    SELECT image FROM constraining_table WHERE type = 'select_me' 
); 
DELETE FROM constraining_table WHERE type = 'select_me'; 
COMMIT; 

Diese Transaktion schlägt fehl. Wenn ich durch Schritt und tun dies manuell, ich bin mit der folgenden Fehlermeldung angezeigt:

ERROR: update or delete on table "delete_from_me" violates foreign key constraint "constraining_table_image_fkey" on table "constraining_table" 
DETAIL: Key (id)=(12345abcde) is still referenced from table "constraining_table". 

Dies ist für eine temporäre Tabelle wie ein guter Kandidat scheint jedoch würde Ich mag wissen, warum es ist, dass Ich kann in dieser Reihenfolge nicht löschen, da die Einschränkungen bis zum Ende der Transaktion nicht wirksam sein sollten.

Antwort

6

Verwenden Sie ON DELETE NO ACTION DEFERRABLE anstelle von ON DELETE RESTRICT DEFERRABLE. Die Verwendung von RESTRICT anstelle von NO ACTION erzwingt, dass die Einschränkung nicht aufschiebbar ist, unabhängig davon, ob Sie den Modifikator DEFERRABLE anwenden. Diese

ist im Kleingedruckten der manual page for CREATE TABLE:

Referenz andere Aktionen als die NO ACTION Prüfung kann nicht verschoben werden, auch wenn der Zwang deferrable deklariert wird.

Offensichtlich enthält der obige Vorbehalt RESTRICT.

Nach kurz nach diesem Satz sind die Definitionen von NO ACTION und RESTRICT:

NO ACTION

zu einem Fehler anzeigt, dass die Löschung oder Aktualisierung eine Fremdschlüssel Einschränkungsverletzung verursachen würde. Wenn die Einschränkung zurückgestellt wird, wird dieser Fehler zur Zeit der Abhängigkeitsprüfung erzeugt, wenn noch Referenzzeilen vorhanden sind. Dies ist die Standardaktion.

RESTRICT

zu einem Fehler anzeigt, dass die Löschung oder Aktualisierung würde eine Fremdschlüsseleinschränkungsverletzung erstellen. Dies ist das gleiche wie KEINE AKTION, außer dass die Prüfung nicht zurückgestellt werden kann.

Wie Sie sehen können, NO ACTION wird identisch zu RESTRICT verhalten, außer NO ACTION deferrable ist. Deshalb empfehle ich es - ich denke, es ist genau das, wonach du verlangst.

Verwandte Themen