Ich habe einen Speicherauszug meiner PostgreSQL-Datenbank erhalten mit:
pg_dump -U user-name -d db-name -f dumpfile
die ich dann in einer anderen datenbank wiederherstelle mit:
psql X -U postgres -d db-name-b -f dumpfile
Mein Problem ist, dass die Datenbank referenzielle Einschränkungen, Überprüfungen und Trigger enthält und einige dieser (Überprüfungen, die es besonders scheinen) während der Wiederherstellung fehlschlagen, da die Informationen nicht in der Reihenfolge geladen werden, in der diese Überprüfungen berücksichtigt würden. Zum Beispiel kann das Einfügen einer Zeile in eine Tabelle mit einer verknüpft sein CHECK
, die eine plpgsql
Funktion aufruft , die prüft, ob eine Bedingung in einer anderen nicht verwandten Tabelle vorliegt. Wenn diese letztere Tabelle nicht psql
vor der ersteren geladen wird , tritt ein Fehler auf.
Das Folgende ist eine SSCCE, die eine solche Datenbank erstellt, die nach dem Sichern pg_dump
nicht wiederhergestellt werden kann:
CREATE OR REPLACE FUNCTION fail_if_b_empty () RETURNS BOOLEAN AS $$
SELECT EXISTS (SELECT 1 FROM b)
$$ LANGUAGE SQL;
CREATE TABLE IF NOT EXISTS a (
i INTEGER NOT NULL
);
INSERT INTO a(i) VALUES (0),(1);
CREATE TABLE IF NOT EXISTS b (
i INTEGER NOT NULL
);
INSERT INTO b(i) VALUES (0);
ALTER TABLE a ADD CONSTRAINT a_constr_1 CHECK (fail_if_b_empty());
Gibt es eine Möglichkeit, alle diese Einschränkungen während der Dump-Wiederherstellung (über die Befehlszeile) zu deaktivieren und anschließend wieder zu aktivieren? Ich verwende PostgreSQL 9.1.
quelle
-X
und-d
Optionen fürpg_dump
.pg_dump
erzeugt ein Dump , die ist in einer leeren DB restorable.CHECK
Einschränkung verweist , werden alle Garantien ungültig, da dies nicht offiziell unterstützt wird, sondern nur toleriert wird. Aber dieCHECK
EinschränkungNOT VALID
zu erklären, hat in jeder Hinsicht für mich funktioniert. Es kann Eckfälle geben, die ich nie angerührt habe ...Antworten:
Sie schlagen also andere Tabellen in einer
CHECK
Einschränkung nach .CHECK
Einschränkungen sollenIMMUTABLE
Prüfungen ausführen . Was für eine Reihe auf einmal als OK eingestuft wird, sollte jederzeit als OK eingestuft werden . So werdenCHECK
Einschränkungen im SQL-Standard definiert. Das ist auch der Grund für diese Einschränkung ( laut Dokumentation ):Jetzt können Ausdrücke in
CHECK
Einschränkungen Funktionen verwenden, auch benutzerdefinierte Funktionen. Diese sollten aufIMMUTABLE
Funktionen beschränkt sein, aber Postgres erzwingt dies derzeit nicht. Nach dieser verwandten Diskussion über pgsql-Hacker besteht ein Grund darin, Verweise auf die aktuelle Zeit zuzulassen, was nichtIMMUTABLE
von Natur aus ist.Sie suchen jedoch nach Zeilen einer anderen Tabelle, was völlig im Widerspruch dazu steht, wie
CHECK
Einschränkungen funktionieren sollen. Ich bin nicht überrascht, dasspg_dump
dies nicht möglich ist.Verschieben Sie Ihren Scheck in einer anderen Tabelle auf einen Trigger (das ist das richtige Werkzeug), und es sollte mit modernen Versionen von Postgres funktionieren.
PostgreSQL 9.2 oder höher
Während das oben Gesagte für jede Version von Postgres zutrifft, wurden mit Postgres 9.2 verschiedene Tools eingeführt, um in Ihrer Situation zu helfen:
Option pg_dump
--exclude-table-data
Eine einfache Lösung wäre, die Datenbank ohne Daten für die verletzende Tabelle zu sichern mit:
Dann hängen Sie einfach die Daten für diese Tabelle am Ende des Dumps an:
Es kann jedoch zu Komplikationen mit anderen Einschränkungen am selben Tisch kommen. Es gibt eine noch bessere Lösung :
NOT VALID
Es gibt den
NOT VALID
Modifikator für Einschränkungen. Nur für FK-Constraints in Version 9.1 verfügbar, wurde jedoch in VersionCHECK
9.2 auf Constraints erweitert . Per Dokumentation:Eine einfache Postgres-Dump-Datei besteht aus drei "Abschnitten":
pre_data
data
post-data
In Postgres 9.2 wurde auch die Option eingeführt, Abschnitte separat mit
-- section=sectionname
auszulagern, dies hilft jedoch nicht bei dem vorliegenden Problem.Hier wird es interessant. Per Dokumentation:
Meine kühne Betonung.
Sie können die anstößige
CHECK
Einschränkung in ändernNOT VALID
, wodurch die Einschränkung in denpost-data
Abschnitt verschoben wird. Löschen und neu erstellen:Dies sollte Ihr Problem lösen. Sie können die Einschränkung sogar in diesem Zustand belassen , da dies die tatsächliche Funktion besser widerspiegelt: Überprüfen Sie neue Zeilen, geben Sie jedoch keine Garantie für vorhandene Daten. An einer Prüfbedingung ist nichts auszusetzen
NOT VALID
. Wenn Sie es vorziehen, können Sie es später validieren:Aber dann sind Sie wieder im Status Quo Ante.
quelle
pg_dump
Trigger am Ende der Speicherauszugsdatei hinzugefügt werden, während dasCHECK
s als Teil desCREATE TABLE
Befehls erstellt wird. Daher hätte die Wiederherstellung auch für den Überprüfungsfall erfolgreich sein können, wenn daspg_dump
Tool einen anderen Ansatz verwendet hätte. Ich verstehe nicht, warum meine DDL in Ordnung ist, wenn ich Trigger verwende, aber nicht in Ordnung, wenn ich Prüfungen verwende, da in beiden Fällen genau dieselbe Logik implementiert ist (Sie können die Version des Skripts anhand von Triggern in meiner eigenen Antwort sehen).pg_dump
sind, dass unterschiedliche DDLs für Prüfbeschränkungen generiert werden sollen (z. B. alle am Ende hinzufügen), sollten Sie diese als Erweiterungsanforderung in die Postgres-Mailingliste aufnehmen. Aber ich stimme Erwin zu, dass Sie Check-Beschränkungen für etwas missbrauchen, für das sie nicht entwickelt wurden. Daher würde ich nicht erwarten, dass diese Änderungsanforderung in naher Zukunft implementiert wird. Übrigens: Ihre SSCCE sollte besser mit einem Fremdschlüssel zwischen den beiden Tabellen modelliert werden.Es scheint, dass dies an der Art
pg_dump
und Weise liegt, wie der Dump erstellt wird. Als ich mir den tatsächlichen Speicherauszug ansah, sah ich, dass dieCHECK
Einschränkung in der Speicherauszugsdatei vorhanden war, und zwar mit der Syntax, die Teil desCREATE TABLE
Befehls ist:Dies führt beim Wiederherstellen der Datenbank zu einem Fehler, da die Prüfung durchgeführt wird, bevor entweder eine Tabelle
a
oder eine Tabelleb
Daten enthält. Wenn jedoch die Dump-Datei bearbeitet undCHECK
stattdessen mit der folgenden Syntax am Ende der Dump-Datei hinzugefügt wird:... dann ist die Restauration kein Problem.
Die exakt gleiche Logik kann mit a
TRIGGER
wie im folgenden Skript implementiert werden :In diesem Fall wird jedoch
pg_dump
(standardmäßig) der Trigger am Ende der Speicherauszugsdatei erstellt (und nicht in derCREATE TABLE
Anweisung wie im Fall einer Überprüfung), sodass die Wiederherstellung erfolgreich ist.quelle