2013-01-06 20 views
41

würde Ich mag Zeilen löschen, die einen Fremdschlüssel enthalten, aber wenn ich so etwas wie dies versuchen:Löschen von Zeilen mit Fremdschlüssel in PostgreSQL

DELETE FROM osoby WHERE id_osoby='1' 

ich diese Aussage erhalten:

ERROR: update or delete on table "osoby" violates foreign key constraint "kontakty_ibfk_1" on table "kontakty" DETAIL: Key (id_osoby)=(1) is still referenced from table "kontakty".

Wie Kann ich diese Zeilen löschen?

+1

Überprüfen Sie dies auch [auf löschen Kaskade] (http://stackoverflow.com/questions/10356484/how-to-add-on-delete-cascade-constraints);) Es ist gut, diese Einstellungen in Ihrer Tabelle zu haben though .. Wenn 'Fremdschlüssel erstellen' wir 'Eltern hinzufügen, dann Kind'. Beim Löschen löschen wir also "child" und dann "eltern";) – bonCodigo

Antwort

42

Um dies zu automatisieren, können Sie den Fremdschlüssel mit ON DELETE CASCADE definieren.
Ich zitiere die the manual of foreign key constraints:

CASCADE specifies that when a referenced row is deleted, row(s) referencing it should be automatically deleted as well.

+4

Wir haben keine Tabellen mit ON 'DELETE CASCADE' erstellt. Ich kann die Struktur von Tabellen nicht ändern. Gibt es eine Möglichkeit, dass Fremdschlüssel automatisch gelöscht werden? oder wir müssen dem von @juergen vorgeschlagenen Weg folgen: – Varun

+1

@Varun: Wenn Sie die Tabelle nicht 'ÄNDERN' können, fügen Sie einen FK mit 'ON DELETE CASCADE' hinzu, löschen Sie dann manuell (einmal) oder durch den Trigger' BEVOR LÖSCHEN '(jedes Mal) sind die restlichen Optionen. –

6

Dies bedeutet, dass Sie in der Tabelle kontakty eine Zeile haben, die auf die Zeile in osoby verweist, die Sie löschen möchten. Sie müssen diese Zeile zuerst löschen oder eine kaskadierende Löschung für die Beziehung zwischen Tabellen festlegen.

Powodzenia!

21

Sie können einen Fremdschlüssel nicht löschen, wenn er immer noch auf eine andere Tabelle verweist. Löschen Sie zuerst den Verweis

delete from kontakty 
where id_osoby = 1; 

DELETE FROM osoby 
WHERE id_osoby = 1; 
12

Man soll dies als eine allgemeine Lösung nicht empfehlen, aber für einmalige Löschen von Zeilen in einer Datenbank, die nicht in der Produktion oder im aktiven Gebrauch ist, können Sie möglicherweise zu Deaktivieren Sie vorübergehend die Trigger für die fraglichen Tabellen.

In meinem Fall bin ich im Entwicklungsmodus und habe ein paar Tabellen, die sich gegenseitig über Fremdschlüssel referenzieren. Daher ist das Löschen ihres Inhalts nicht so einfach wie das Entfernen aller Zeilen von einer Tabelle vor der anderen. Also, für mich, es funktionierte gut ihre Inhalte zu löschen, wie folgt:

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 hinzufügen WHERE-Klauseln, wie gewünscht, natürlich mit Sorgfalt um die Integrität der Datenbank nicht zu untergraben.

Es gibt einige gute, verwandte Diskussion auf http://www.openscope.net/2012/08/23/subverting-foreign-key-constraints-in-postgres-or-mysql/

3

Es ist eine Weile her, seit diese Frage gestellt wurde, kann Hoffnung helfen. Da Sie die db-Struktur nicht ändern oder ändern können, können Sie dies tun. nach der postgresql docs.

TRUNCATE - eine Tabelle oder einen Tabellensatz leeren.

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 unqualifiziertes DELETE für jede Tabelle, aber da es die Tabellen nicht wirklich scannt, ist es schneller. Darüber hinaus wird der Speicherplatz sofort zurückgewonnen, anstatt eine nachfolgende VACUUM-Operation zu erfordern. Dies ist besonders bei großen Tabellen nützlich.


Kürzen der Tabelle othertable und Kaskade auf irgendwelche Tabellen, die othertable über Fremdschlüssel-Constraints Referenz:

TRUNCATE othertable CASCADE; 

die gleichen, und zurückgesetzt auch alle zugehörigen Sequenzgeneratoren:

TRUNCATE bigtable, fattable RESTART IDENTITY; 

Alle zugehörigen Sequenzgeneratoren abschneiden und zurücksetzen:

TRUNCATE revinfo RESTART IDENTITY CASCADE ;