すでにレコードがあるテーブルにデフォルト値を設定せずにNOT NULL制約をつけたカラムを追加しようとすると、追加したカラムのレコードの値をNULLにする訳にはいかずエラーになってしまします。
これらに対応するには一度デフォルト値を指定する方法と、値をプログラム側で変更する2つの方法がありそうなのでSQLとRailsのmigrationで試してみました。
一度デフォルト値を指定する
- デフォルト値、NOT NULL制約を指定したカラムを追加
- default値の設定を外す
この方法はアプリケーションを動かしながら変更できるという利点があるので、この方法で十分な場合はこの方法を使うと良いと思います。
SQL
ALTER TABLE users ADD group_id int DEFAULT 1 NOT NULL;
ALTER TABLE users MODIFY group_id int(11) NOT NULL;
Ruby on Rails(migrationファイル)
def up
add_column :users, :group_id, :integer, null: false, default: 1
change_column_default :users, :group_id, nil
end
値をプログラム側で変更する方法
- NOT NULL制約を指定しないカラムを追加
- もともとあったレコードの追加したカラムのレコードに値を入れる
- NOT NULL制約の設定に変更する
この方法は過去のデータをプログラム側で制御できるという利点があります。 ただし、アプリケーションを動かしながらだと過去のレコード追加してからNOT NULL制約をつけるまでに新しくレコードが入ってしまうとエラーが出てしまうという問題があるので一度止める必要がありそうです。
SQL
ALTER TABLE users ADD group_id int;
UPDATE users SET users.group_id = 1;
ALTER TABLE users MODIFY group_id int(11) NOT NULL;
Ruby on Rails(migrationファイル)
def up
add_column :users, :group_id, :integer
User.update_all(group_id: 1)
change_column_null :users, :group_id, false
end