1

Ich habe eine Spalte in meiner Postgres-DB-Tabelle, die ein boolescher Typ ist. Ich möchte es in eine ganze Zahl ändern, weil ich in dieser Spalte mehr als nur wahr/falsch brauche.Ändern des booleschen Spaltentyps in int

Ich möchte auch in Rails 2.

geschieht dies einfach alle die wahren Werte zu 1 und die falschen Werte ändern? Ich habe versucht, dies über eine Migrationsdatei und migrieren meine DB.

+0

Das klingt wie ein XY-Problem, wo Sie nach Y fragen, aber sollten nach X gefragt haben, was zu Y führte. Mit anderen Worten, Sie sollten nach dem Schema und den Daten fragen, die Sie speichern und warum, anstatt zu modifizieren die Tabelle und versuchen, Wahr und Falsch zu ganzen Zahlen zu bilden, dann das gleiche Feld für andere Dinge zu verwenden. –

Antwort

2

Müssen Sie wirklich die Datenbank dafür ändern? Eine mögliche Lösung besteht darin, nur eine Wrapper-Methode zu erstellen, die dies für Sie übernimmt. Nehmen wir an, Sie haben eine boolesche Spalte mit dem Namen , dann könnten Sie einfach eine Wrappermethode schreiben, die diese Logik transparent verarbeitet, ohne die zugrunde liegende Datenbank zu ändern.

im Modell Active:

def mycol 
    read_attribute(:boolcol) ? 1 : 2 
end 

def mycol=(value) 
    write_attribute(:mycol, value == 1) 
end 

So zum Beispiel u.mycol = 1 && u.save läuft in die Datenbank schreiben würde false und u.reload.mycol würde 1.

jedoch zurückkehren, wenn es wirklich notwendig ist, zu tun Eine Migration erstellt dann eine neue Ganzzahlspalte, um die ursprüngliche boolesche Spalte zu ersetzen. Entfernen oder ändern Sie die vorhandene Spalte nicht, um sicherzustellen, dass Sie keine Daten beschädigen oder zerstören.

Erstellen Sie nach dem Erstellen der neuen Spalte eine Rake-Task, um alle vorhandenen Datensätze zu durchlaufen (verwenden Sie die Methode find_each für die Iteration), und legen Sie den ganzzahligen Wert für die neue Spalte basierend auf dem Wert der ursprünglichen booleschen Spalte fest. Nachdem Sie die Integrität der Daten überprüft haben, können Sie die ursprüngliche boolesche Spalte löschen und durch die neu erstellte Spalte ersetzen.

+1

Danke. Das macht Sinn :) (Ich werde dem zweiten Vorschlag folgen) – learningruby347

+0

Eigentlich ist es möglich, alles in der Migrationsdatei zu tun. Ich arbeite an meiner lokalen Maschine so wenig Risiko von up Daten. – learningruby347

+0

Möglich ja, aber vorsichtig dabei sein.Es kann Probleme verursachen, wenn Sie zu einem späteren Zeitpunkt Migrationen ausführen oder wenn eine Migration zweimal ausgeführt wird (Nicht-Idempotenz). Auch wenn Ihr Schema zwischen test/dev/prod konsistent ist, verursachen die zugrunde liegenden Daten möglicherweise keine unerwarteten fehlgeschlagenen Migrationen und weitere Probleme. –

5

Ja, Sie können diese Änderung mit einer einzigen Migration durchführen. Der einzige knifflige Teil ist, dass Sie der Datenbank mitteilen müssen, wie die booleschen Werte in ganze Zahlen konvertiert werden.

Der Weg, dies zu tun ist, eine USING Klausel in der ALTER TABLE zu verwenden, um das Mapping bereitzustellen. Die rohe SQL-Version würde wie folgt aussehen:

alter table models 
alter column c type integer 
using case when c then 1 else 2 end 

und übersetzt zu einer Migration thusly:

def change 
    change_column :models, :c, :integer, :using => 'case when c then 1 else 2 end' 
end 

Eine boolean Spalte kann nur enthalten TRUE oder FALSE so dass eine einfache CASE ausreichend sein sollte. Wenn Sie erlauben NULL s und wollen, dass sie erhalten dann:

:using => 'case when c is null then null when c then 1 else 2 end' 

sollte es tun.

Natürlich müssen Sie alle Ihre Code aktualisieren, um richtig mit diesen neuen Ganzzahlen von Hand arbeiten.