2009-02-04 7 views
180

ich das Hinzufügen eine neue, „NOT NULL“ Spalte meiner PostgreSQL-Datenbank der folgende Abfrage verwenden (für das Internet hygienisiert):Wie kann ich eine Spalte zu einer Postgresql-Datenbank hinzufügen, die Nullen nicht zulässt?

ALTER TABLE mytable ADD COLUMN mycolumn character varying(50) NOT NULL; 

Jedes Mal, wenn ich diese Abfrage ausführen, erhalte ich folgende Fehlermeldung:

ERROR: column "mycolumn" contains null values 

ich bin ratlos. Wo gehe ich falsch?

HINWEIS: Ich benutze primär pgAdmin III (1.8.4), aber ich habe den gleichen Fehler erhalten, wenn ich die SQL aus Terminal ausgeführt habe.

Antwort

305

Sie müssen einen Standardwert festlegen.

ALTER TABLE mytable ADD COLUMN mycolumn character varying(50) NOT NULL DEFAULT 'foo'; 

... some work (set real values as you want)... 

ALTER TABLE mytable ALTER COLUMN mycolumn DROP DEFAULT; 
+1

Schöne Lösung. Ich konnte aus irgendeinem Grund nicht zu den Online-Postgres-Dokumenten gelangen, um zu sehen, wie die Syntax dafür aussehen würde. –

+3

@SeanBright, du kannst offline auf postgres doc zugreifen, indem du 'man ALTER_TABLE' tust :) –

+0

@ allan.simon Ich habe PostgreSQL noch nie benutzt und ich habe es nirgendwo installiert. –

47

Da in der Tabelle bereits Zeilen vorhanden sind, versucht die Anweisung ALTER, NULL in die neu erstellte Spalte für alle vorhandenen Zeilen einzufügen. Sie müssten die Spalte so hinzufügen, dass sie NULL zuläßt, dann füllen Sie die Spalte mit den gewünschten Werten und setzen sie danach auf NOT NULL.

+6

Beispiel dafür, wie es wirklich schön gewesen, zu tun hätte. Ansonsten scheint Lucs Lösung vollständiger und gebrauchsfertig zu sein. –

+1

Finden Sie diese Antwort für ein Beispiel: http://StackOverflow.com/a/516016/32453 – rogerdpack

5

Sie müssen entweder einen Standardwert definieren oder tun, was Sean sagt, und fügen Sie ihn ohne die Null-Einschränkung hinzu, bis Sie ihn in die vorhandenen Zeilen eingefügt haben.

1

Oder erstellen Sie eine neue Tabelle als temp mit der zusätzlichen Spalte, kopieren Sie die Daten in diese neue Tabelle und manipulieren Sie sie bei Bedarf, um die neue Spalte ohne NULL-Werte zu füllen und dann die Tabelle durch eine Namensänderung in zwei Schritten zu tauschen .

Ja, es ist komplizierter, aber Sie müssen es möglicherweise auf diese Weise tun, wenn Sie keine große UPDATE auf einem Live-Tisch wollen.

+3

Ich habe nicht -1 Sie, aber ich denke, es kann subtile Schwierigkeiten mit diesem - z.B. Ich wette, dass bestehende Indizes, Trigger und Views auch nach dem Umbenennen weiterhin auf die Originaltabelle verweisen, da ich denke, dass sie das Relid der Tabelle (die sich nicht ändert) statt ihres Namens speichern. –

+1

Ja, ich hätte sagen sollen, dass die neue Tabelle eine exakte Kopie des Originals sein sollte, einschließlich der Hinzufügung von Indizes und ähnlichem. Mein Fehler, zu kurz zu sein. Der Grund dafür ist, dass es auch subtile Schwierigkeiten gibt, einen ALTER auf einem Tisch auszuführen, der live sein kann, und manchmal müssen Sie ihn inszenieren. – alphadogg

+0

Wenn Sie beispielsweise den DEFAULT-Ansatz verwenden, fügen Sie diesen Standardwert jeder Zeile hinzu. Ich bin mir nicht sicher, wie Postgres einen Tisch blockiert. Wenn die Spaltenreihenfolge wichtig ist, können Sie nicht einfach eine Spalte mit dem ALTER-Befehl hinzufügen. – alphadogg

2

einen Standardwert angeben würde auch funktionieren, vorausgesetzt, ein Standardwert angemessen ist.

+1

Es würde die Antwort verbessern, um die geänderte Syntax zum Erstellen der Spalte mit einem Standardwert (zur Veranschaulichung) zu geben. – hardmath

52

Wie andere beobachtet haben, müssen Sie entweder eine Nullwert-Spalte erstellen oder einen DEFAULT-Wert angeben. Wenn das nicht flexibel genug, um (zB wenn Sie den neuen Wert für jede Zeile einzeln irgendwie berechnet werden), können Sie die Tatsache nutzen, dass in PostgreSQL, alle DDL-Befehle können innerhalb einer Transaktion ausgeführt werden:

BEGIN; 
ALTER TABLE mytable ADD COLUMN mycolumn character varying(50); 
UPDATE mytable SET mycolumn = timeofday(); -- Just a silly example 
ALTER TABLE mytable ALTER COLUMN mycolumn SET NOT NULL; 
COMMIT; 
+1

selbst in einer Transaktion, NOT NULL wird sofort erzwungen, so muss zuerst Spalte hinzufügen, Werte füllen, dann fügen Sie NOT NULL - wie diese Antwort tut. (getestet auf Postgres 9.6) –

0

diese Abfrage wird automatisch zu aktualisieren, um die nulls

ALTER TABLE mytable ADD COLUMN mycolumn character varying(50) DEFAULT 'whatever' NOT NULL; 
-3

Das ist für mich gearbeitet: :)

ALTER TABLE your_table_name ADD COLUMN new_column_name int; 
+1

Es gibt keine 'NOT NULL'-Einschränkung für Ihre Abfrage. Natürlich funktioniert es. – Sylvain