Ich möchte Zeilen löschen, die einen Fremdschlüssel enthalten, aber wenn ich so etwas versuche:
DELETE FROM osoby WHERE id_osoby='1'
Ich bekomme diese Aussage:
FEHLER: Aktualisieren oder Löschen in der Tabelle "osoby" verletzt die Fremdschlüsseleinschränkung "kontakty_ibfk_1" in der Tabelle "kontakty". DETAIL: Der Schlüssel (id_osoby) = (1) wird weiterhin aus der Tabelle "kontakty" referenziert.
Wie kann ich diese Zeilen löschen?
sql
postgresql
foreign-keys
cascading-deletes
Michal Loksik
quelle
quelle
creating foreign keys
wiradd parent then child
. Also beim Löschen wirdelete child and then parent
;)Antworten:
Um dies zu automatisieren, können Sie die Fremdschlüsseleinschränkung mit definieren
ON DELETE CASCADE
.Ich zitiere das Handbuch der Fremdschlüsseleinschränkungen :
Schlagen Sie die aktuelle FK-Definition folgendermaßen nach:
SELECT pg_get_constraintdef(oid) AS constraint_def FROM pg_constraint WHERE conrelid = 'public.kontakty'::regclass -- assuming pubic schema AND conname = 'kontakty_ibfk_1';
Fügen Sie dann das
ON DELETE ...
TeilON DELETE CASCADE
in einer Anweisung wie folgt hinzu oder ändern Sie es (wobei alles andere unverändert bleibt):ALTER TABLE kontakty DROP CONSTRAINT kontakty_ibfk_1 , ADD CONSTRAINT kontakty_ibfk_1 FOREIGN KEY (id_osoby) REFERENCES osoby (id_osoby) ON DELETE CASCADE;
Da es keine
ALTER CONSTRAINT
Syntax gibt, löschen Sie die Einschränkung und erstellen Sie sie in einer einzelnenALTER TABLE
Anweisung neu. Dies vermeidet mögliche Rennbedingungen bei gleichzeitigem Schreibzugriff.Dazu benötigen Sie natürlich die Berechtigungen. Die Operation nimmt eine
ACCESS EXCLUSIVE
Sperre für den Tischkontakty
und eineSHARE ROW EXCLUSIVE
Sperre für den Tischosoby
.Wenn Sie
ALTER
die Tabelle nicht können, können Sie sie nur noch einmal (einmal) oder per TriggerBEFORE DELETE
(jedes Mal) löschen .quelle
DELETE CASCADE
. Ich kann die Struktur von Tabellen nicht ändern. Gibt es eine Möglichkeit, Fremdschlüssel automatisch zu löschen? oder wir müssen dem von @juergen dALTER
die Tabelle nicht zum Hinzufügen eines FK verwenden könnenON DELETE CASCADE
, sind das Löschen per Hand (einmal) oder per TriggerBEFORE DELETE
(jedes Mal) die verbleibenden Optionen.ON DELETE CASCADE
, der Spalte mit dem Fremdschlüssel in Ihrer create-Anweisung etwas hinzuzufügen .\d kontakty
Sie können einen Fremdschlüssel nicht löschen, wenn er noch auf eine andere Tabelle verweist. Löschen Sie zuerst die Referenz
delete from kontakty where id_osoby = 1; DELETE FROM osoby WHERE id_osoby = 1;
quelle
Dies sollte nicht als allgemeine Lösung empfohlen werden. Für das einmalige Löschen von Zeilen in einer Datenbank, die sich nicht in der Produktion befindet oder nicht aktiv verwendet wird, können Sie möglicherweise die Trigger für die betreffenden Tabellen vorübergehend deaktivieren.
In meinem Fall bin ich im Entwicklungsmodus und habe einige Tabellen, die über Fremdschlüssel aufeinander verweisen. Das Löschen des Inhalts ist daher nicht ganz so einfach wie das Entfernen aller Zeilen aus einer Tabelle vor der anderen. Für mich hat es also gut funktioniert, den Inhalt wie folgt zu löschen:
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;
Sie sollten in der Lage sein, WHERE-Klauseln wie gewünscht hinzuzufügen, natürlich mit Vorsicht, um die Integrität der Datenbank nicht zu beeinträchtigen.
Es gibt einige gute, verwandte Diskussionen unter http://www.openscope.net/2012/08/23/subverting-foreign-key-constraints-in-postgres-or-mysql/
quelle
Es ist eine Weile her, seit diese Frage gestellt wurde, Hoffnung kann helfen. Da Sie die Datenbankstruktur nicht ändern können, können Sie dies tun. gemäß den postgresql docs .
TRUNCATE - Leert eine Tabelle oder einen Satz von Tabellen.
TRUNCATE [ TABLE ] [ ONLY ] name [ * ] [, ... ] [ RESTART IDENTITY | CONTINUE IDENTITY ] [ CASCADE | RESTRICT ]
Beschreibung
TRUNCATE entfernt schnell alle Zeilen aus einer Reihe von Tabellen. Es hat den gleichen Effekt wie ein nicht qualifiziertes LÖSCHEN für jede Tabelle, aber da es die Tabellen nicht tatsächlich scannt, ist es schneller. Darüber hinaus wird sofort Speicherplatz zurückgewonnen, anstatt eine nachfolgende VACUUM-Operation zu erfordern. Dies ist am nützlichsten bei großen Tabellen.
Schneiden Sie die Tabelle othertable ab und kaskadieren Sie über Fremdschlüsseleinschränkungen zu allen Tabellen, die auf othertable verweisen:
TRUNCATE othertable CASCADE;
Das gleiche und auch alle zugehörigen Sequenzgeneratoren zurücksetzen:
TRUNCATE bigtable, fattable RESTART IDENTITY;
Schneiden Sie alle zugehörigen Sequenzgeneratoren ab und setzen Sie sie zurück:
TRUNCATE revinfo RESTART IDENTITY CASCADE ;
quelle
Dies bedeutet, dass Sie in der Tabelle
kontakty
eine Zeile haben, die auf die Zeile verweist, in derosoby
Sie löschen möchten. Sie müssen diese Zeile zuerst löschen oder eine Kaskadenlöschung für die Beziehung zwischen Tabellen festlegen.Powodzenia!
quelle