Postgres: Standardwert für die Spalte (string) kann nicht gewirkt werden, automatisch zu Typ enum
Ich habe eine status
Spalte in einer Tabelle, ich will ein enum. Ursprünglich hatte ich vor, erstellt das Feld als integer, und dachte, ich würde verwenden, den eingebauten Schienen, die enum-Funktionalität. Stellt sich heraus, dass erfordert die mindestens Rails 4.1, aber ich bin mit 4.0 und der Prozess der Aktualisierung wird einige Zeit in Anspruch nehmen.
Aber, darüber nachzudenken, wie das alles funktioniert, ich erkannte, dass ich kann haben entweder ein ActiveRecord enum oder eine postgres-enum, nicht für beide. Ich dachte, dass auf lange Sicht eine explizite postgres enum wäre am besten. Also schrieb ich eine migration zu konvertieren, die status
Spalte von integer in einen enum.
execute "CREATE TYPE status_options AS ENUM ('pending', 'declined', 'approved');"
change_column :site_applications, :status, "status_options USING status::status_options"
Aber, ich bekomme diese Fehlermeldung:
PG::CannotCoerce: ERROR: cannot cast type integer to status_options
ALTER TABLE "site_applications" ALTER COLUMN "status" TYPE status_options USING status::status_options
Alles, was ich bisher gesehen habe, in meinem searchings sagt mir, dass sollte gearbeitet haben,, aber es funktioniert nicht. Ich dachte, vielleicht ist das problem, dass ich einfach nicht gehen aus integer enum. So soll es sein. Meine Lösung war, um zuerst konvertieren Sie die Spalte in eine Zeichenfolge und dann versuchen, es zu konvertieren enum.
change_column :site_applications, :status, :string
execute "CREATE TYPE status_options AS ENUM ('pending', 'declined', 'approved');"
change_column :site_applications, :status, "status_options USING status::status_options"
... Und das gibt mir die folgende Fehlermeldung:
PG::DatatypeMismatch: ERROR: default for column "status" cannot be cast automatically to type status_options
ALTER TABLE "site_applications" ALTER COLUMN "status" TYPE status_options USING status::status_options
Führte mich zu glauben, dass dies etwas zu tun hatte mit der default-Wert, also versuchte ich die Angabe des Standard in der change_column
Erklärung:
change_column :site_applications, :status, :string, default: "pending"
Dass die änderungen erfolgreich die Spalte in eine Zeichenfolge der Standardwert ist "offen", aber change_column
schlägt mit der gleichen "default für die Spalte" Fehler.
Merke ich, dass ich konnte einfach legen Sie die Spalte alle zusammen und erstellen Sie dann es genau so, wie ich will, aber an diesem Punkt ist es eine Frage der nachkommenschaft. Warum zum Teufel kann ich nicht konvertieren, eine Spalte von integer oder string zu enum? Wer?
UPDATE MIT AKZEPTIERTEN ANTWORTEN
Basierend auf Gary ' s Antwort da unten, dies ist die migration, arbeitete.
def up
execute "ALTER TABLE site_applications ALTER status DROP DEFAULT;"
execute "CREATE TYPE status_options AS ENUM ('pending', 'declined', 'approved');"
change_column :site_applications, :status, "status_options USING status::status_options", default: "pending"
end
def down
change_column :site_applications, :status, :string, default: "pending"
execute "DROP TYPE status_options;"
end
- Können Sie das zeigen die Ergebnisse einer \dt site_applications in PSQL. Da die Nachricht klingt wie es ist ein Standard-Wert gesetzt gegen die Spalte. Möglicherweise müssen Sie entfernen die Standard -, während Sie die änderung vornehmen und dann wieder hinzufügen einer Voreinstellung des entsprechenden Typs hinterher.
- Ich denke, Sie sind absolut Recht, aber ich kann nicht für das Leben von mir herauszufinden, welche Art von default zu setzen, so dass es sein kann, wechselte zu einem enum. Aber, ich habe die
\dt schema.site_applications
- und das ist es, was zurückgegeben:schema | site_applications | table | eliduke
- sorry, sollte Es gewesen sein \d statt \dt
- Oh, ok. Hier ist das:
status | integer | not null default 0
. Aber ich bin nicht überrascht, dass, wirklich, weil, wenn ich versuchte, Sie zu konvertieren integer enum, ich habe Fehlercannot cast type integer to status_options
. So, ich dachte, dass da ein enum ist eine Art Variante von einem string, der zunächst würde ich es in einen string konvertieren und dann konvertieren Sie Sie in enum. Und DAS ist, wenn ich bekam diedefault for column
Fehler. An einer Stelle habe ich sogar versucht, die Umwandlung der integer in einen string und setzen den Standard für die string-Spalte auf null und dann die Umwandlung zu enum. Das scheiterte auch mit dem gleichen Fehler. - In diesem Fall werden Sie wollen, ein
alter table schema.site_applications alter status drop default
zu entfernen, die den Standard vollständig. konvertieren Sie den Typ, dannalter table schema.site_applications alter status set default 'pending'::status_options'
nicht ganz sicher, ob der Standard-enum-syntax. - Das war der Gewinner! Vielen Dank, @Gary. Wenn Sie möchten, schreiben Sie eine Antwort werde ich Holen, die als die Antwort.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Müssen Sie entfernen Sie den Standardwert aus der Spalte vor der änderung als Standard ist eingestellt auf einen Wert, der gültig ist für die alte Spalte Typ aber nicht kompatibel mit der neuen Art.
Dann können Sie ändern Sie die Spalte Typ. Schließlich, wenn die neue Spalte vom Typ angewendet wird, können Sie hinzufügen eine neue Standard gegen den Tisch.