2014-02-27 5 views
6

Ich habe eine Tabelle, nennen wir es MyTable. Es ist Teil einer Postgresql-Datenbank.Hinzufügen NOT NULL Feld ohne Standardwert in eine befüllte DB

In MyTable sind viele Einträge, sagen wir über eine Million. Ich möchte ein Feld zu dieser Tabelle hinzufügen, nennen wir es MyNewField. Es wird von einer ActiveRecord-Migration hinzugefügt.

Dieses Feld darf keine Standardwerte enthalten und darf nicht Nullwerte enthalten. Das Ergebnis, in es Migration Klasse ist so etwas wie so wäre:

class AddMyFieldToMyTable < ActiveRecord::Migration 
    def change 
    add_column :my_table, :my_field, :text, null: false 
    end 
end 

Allerdings wird es einen Fehler auslösen (PG :: NotNullViolation), da die Tabelle bereits Zeilen enthält, die alle die MyField auf NULL gesetzt haben.

Was ich tun möchte, ist: Fügen Sie die Zeile ohne Standardwert und Nullable auf false (ohne ein PG :: NotNullViolation auslösen). Fügen Sie dann einen Wert aus einer anderen Tabelle in jeden Datensatz ein.

Dies wäre wahrscheinlich erreichbar, indem das Feld mit Nullable auf true gesetzt wird, dann die Werte addiert werden und dann wieder auf nullable gesetzt wird, um auf false zu setzen. Ich bin jedoch interessiert zu wissen, ob es möglich ist, dies in einem einzigen Schuss zu tun.

Antwort

6

Sie müssen sicherstellen, dass die andere Tabelle den Wert my_field für jeden Eintrag in my_table hat.

class AddMyFieldToMyTable < ActiveRecord::Migration 
    def up 
    add_column :my_table, :my_field, :text 
    execute("insert into my_table(my_field) values (select my_field from different_table where my_table.id = different_table.different_id)") 
    change_column :my_table, :my_field, :text, null: false 
    end 

    def down 
    remove_column :my_table, :my_field 
    end 
end 
1

alle Indikationen scheint, dass dies möglich nicht sein wird, um zu zeigen, in einem Schuss zu tun; Sie müssen die Spalte ohne die Null-Integritätsbedingung hinzufügen, die Daten auffüllen und anschließend die Null-Integritätsbedingung hinzufügen.

class AddMyFieldToMyTable < ActiveRecord::Migration 
    def change 
    add_column :my_table, :my_field, :text 
    reversible do |dir| 
     dir.up do 
     # populate my_field col 
     change_column :my_table, :my_field, :text, null: false 
     end 
    end 
    end 
end 

Ressourcen:


Wenn Sie wirklich nur die Spalte einmal einstellen wollen, vielleicht könnten Sie es mit einem temporären Standardwert generieren dann aktualisieren Sie es sofort mit den echten Daten.

class AddMyFieldToMyTable < ActiveRecord::Migration 
    def change 
    add_column :my_table, :my_field, :text, default: 'tmp', null: false 
    reversible do |dir| 
     dir.up do 
     # populate my_field col 
     end 
    end 
    end 
end 
Verwandte Themen