[Ruby on Rails][SQLite3] SQLException: Cannot add a NOT NULL column with default value NULL

Ruby on Rails にて、Usersテーブルに role カラムを NOT NULL 制約を付けて、追加しようとしたらエラーが発生しました。

■ エラーが発生した migration ファイル

db/migrate/20120415053115_add_role_to_users.rb

class AddRoleToUsers < ActiveRecord::Migration
  def change
    add_column :users, :role, :string, :null => false
  end
end

rake db:migrate すると、エラーが発生しました。

■ エラーメッセージ

$ rake db:migrate
==  AddRoleToUsers: migrating ============================
-- add_column(:users, :role, :string, {:null=>false})
rake aborted!
An error has occurred, this and all later migrations canceled:
 
SQLite3::SQLException: Cannot add a NOT NULL column with default value NULL: ALTER TABLE "users" ADD "role" varchar(255) NOT NULL
 
Tasks: TOP => db:migrate
(See full trace by running task with --trace)

SQLite3 では、NOT NULL制約を付ける場合にはNULL以外のDEFAULTを指定する必要があるみたいです。

DEFAULT を指定しないと NULL が入ってしまうので、そのせいで今回のエラーが発生したみたいです。

NOT NULL制約を付ける場合にはNULL以外のDEFAULTを指定して下さい

・引用元:さぼてん: SQLite でテーブルの変更・カラムの追加をする-ALTER TABLE はてなブックマーク - さぼてん: SQLite でテーブルの変更・カラムの追加をする-ALTER TABLE

なので、下記のようにカラム追加後に change_column で role カラムを NOT NULL に変更すればOKです。

class AddRoleToUsers < ActiveRecord::Migration
  def change
    add_column :users, :role, :string, :null => false
    change_column :users, :role, :string, :null => false
  end
end

また、素直に DEFAULT を指定してあげるのも一つの手です。

class AddRoleToUsers < ActiveRecord::Migration
  def change
    add_column :users, :role, :string, :null => false, :default => ""
  end
end

以上です。

【参考】

ruby on rails – SQLite3::SQLException: Cannot add a NOT NULL column with default value NULL – Stack Overflow はてなブックマーク - ruby on rails - SQLite3::SQLException: Cannot add a NOT NULL column with default value NULL - Stack Overflow