Hier ist eine kurze und süße Version mit der Anweisung "DO":
DO $$
BEGIN
BEGIN
ALTER TABLE <table_name> ADD COLUMN <column_name> <column_type>;
EXCEPTION
WHEN duplicate_column THEN RAISE NOTICE 'column <column_name> already exists in <table_name>.';
END;
END;
$$
Sie können diese nicht als Parameter übergeben. Sie müssen die Variablen auf der Clientseite in der Zeichenfolge ersetzen. Dies ist jedoch eine eigenständige Abfrage, die nur dann eine Nachricht ausgibt, wenn die Spalte bereits vorhanden ist. Wenn dies nicht der Fall ist, wird eine hinzugefügt schlägt weiterhin bei anderen Fehlern fehl (z. B. bei einem ungültigen Datentyp).
Ich empfehle keine dieser Methoden, wenn es sich um zufällige Zeichenfolgen handelt, die aus externen Quellen stammen. Unabhängig davon, welche Methode Sie verwenden (cleint- oder serverseitige dynamische Zeichenfolgen, die als Abfragen ausgeführt werden), ist dies ein Rezept für eine Katastrophe, da Sie dadurch SQL-Injection-Angriffe ausführen können.
DO $$ BEGIN BEGIN CREATE INDEX type_idx ON table1 USING btree (type); EXCEPTION WHEN duplicate_table THEN RAISE NOTICE 'Index exists.'; END; END;$$;
der gleiche Ansatz inCREATE INDEX
;) Danke für Ihre Antwort,DO $$
fehlschlägt. Ich habe versucht,DO $$;
was auch fehlschlägt, bis ich gerade den Block gestartet habe, mitDO $$DECLARE r record;
dem in einem Beispiel in den dev postgres-Dokumenten angegeben ist .END; $$
ist ein Syntaxfehler (Postgres 9.3), den ichEND $$;
stattdessen verwenden mussteEXCEPTION
) ist etwas allgemeiner und kann beispielsweise für Aufgaben ohneIF NOT EXISTS
Syntax verwendet werdenALTER TABLE ... ADD CONSTRAINT
.Mit Postgres 9.6 kann dies mit der Option erfolgen
if not exists
quelle
ADD CONSTRAINT IF NOT EXISTS
.Anruf:
Gibt
TRUE
bei Erfolg zurück, sonstFALSE
(Spalte existiert bereits).Löst eine Ausnahme für einen ungültigen Tabellen- oder Typnamen aus.
Warum eine andere Version?
Dies könnte mit einer
DO
Anweisung erfolgen, aberDO
Anweisungen können nichts zurückgeben. Und wenn es für den wiederholten Gebrauch ist, würde ich eine Funktion erstellen.Ich verwende den Objekt - ID - Typen
regclass
undregtype
für_tbl
und_type
welche a) verhindert SQL - Injection und b) prüft Gültigkeit sowohl unmittelbar (billigste Art und Weise). Der Spaltenname_col
muss noch mit bereinigtEXECUTE
werdenquote_ident()
. Weitere Erklärungen in dieser verwandten Antwort:format()
erfordert Postgres 9.1+. Bei älteren Versionen manuell verketten:Sie können Ihren Tabellennamen schemaqualifizieren, müssen dies aber nicht.
Sie können die Bezeichner im Funktionsaufruf in doppelte Anführungszeichen setzen, um Wörter in Groß- und Kleinschreibung und reservierte Wörter beizubehalten (aber Sie sollten sowieso nichts davon verwenden).
Ich frage
pg_catalog
statt derinformation_schema
. Ausführliche Erklärung:Blöcke, die eine
EXCEPTION
Klausel wie die aktuell akzeptierte Antwort enthalten, sind wesentlich langsamer. Dies ist im Allgemeinen einfacher und schneller. Die Dokumentation:quelle
DO
Aussage, eine geringfügige Änderung, die akzeptiert werden muss,DEFAULT
und dies hat perfekt funktioniert!Die folgende Auswahlabfrage wird
true/false
mit derEXISTS()
Funktion zurückgegeben.Verwenden Sie die folgende dynamische SQL-Anweisung, um Ihre Tabelle zu ändern
quelle
Für diejenigen, die Postgre 9.5+ verwenden (ich glaube, die meisten von Ihnen), gibt es eine recht einfache und saubere Lösung
quelle
Die folgende Funktion überprüft die Spalte, falls vorhanden, und gibt die entsprechende Nachricht zurück. Andernfalls wird die Spalte zur Tabelle hinzugefügt.
quelle
Dies ist im Grunde die Lösung von Sola, aber nur ein bisschen aufgeräumt. Es ist anders genug, dass ich nicht nur seine Lösung "verbessern" wollte (außerdem finde ich das irgendwie unhöflich).
Der Hauptunterschied besteht darin, dass das EXECUTE-Format verwendet wird. Was ich für etwas sauberer halte, aber meiner Meinung nach bedeutet, dass Sie auf PostgresSQL 9.1 oder neuer sein müssen.
Dies wurde auf 9.1 getestet und funktioniert. Hinweis: Es wird ein Fehler ausgegeben, wenn das Schema / der Tabellenname / oder der Datentyp ungültig sind. Das könnte "behoben" werden, könnte aber in vielen Fällen das richtige Verhalten sein.
Verwendung:
quelle
Kann zu Migrationsskripten hinzugefügt werden, ruft die Funktion auf und löscht sie, wenn sie fertig ist.
quelle
In meinem Fall ist es aus Gründen der Erstellung für unsere Migrationsskripte etwas schwierig, verschiedene Schemas zu überschneiden.
Um dies zu umgehen, haben wir eine Ausnahme verwendet, die den Fehler nur abgefangen und ignoriert hat. Dies hatte auch den schönen Nebeneffekt, dass es viel einfacher anzusehen war.
Seien Sie jedoch vorsichtig, dass die anderen Lösungen ihre eigenen Vorteile haben, die diese Lösung wahrscheinlich überwiegen:
quelle
Sie können dies folgendermaßen tun.
Die Spalte wird also gelöscht, wenn sie bereits vorhanden ist. Fügen Sie dann die Spalte einer bestimmten Tabelle hinzu.
quelle
Überprüfen Sie einfach, ob die Abfrage einen Spaltennamen zurückgegeben hat.
Wenn nicht, führen Sie Folgendes aus:
Wo Sie etwas Nützliches für 'x' und 'y' setzen und natürlich einen geeigneten Datentyp, bei dem ich int verwendet habe.
quelle