In my Rails (3.2) app, I have a bunch of tables in my database but I forgot to add a few not null constraints. How can I write a migration which adds not null to an existing column?
6 Answers
You can also use change_column_null:
change_column_null :table_name, :column_name, false
4 Comments
For Rails 4+, nates' answer (using change_column_null) is better.
Pre-Rails 4, try change_column.
5 Comments
:limit constraint), you need to repeat those attributes when using change_column, or they will be lost. For this reason, I prefer to use change_column_nullIrreversibleMigration which may not be what you want.Add column with default value
Remove default value
add_column :orders, :items, :integer, null: false, default: 0
change_column :orders, :items, :integer, default: nil
1 Comment
If you are using it on a new create migration script/schema here is how we can define it
class CreateUsers < ActiveRecord::Migration[5.2]
def change
create_table :users do |t|
t.string :name, null: false # Notice here, NOT NULL definition
t.string :email, null: false
t.string :password, null: false
t.integer :created_by
t.integer :updated_by
t.datetime :created_at
t.datetime :updated_at, default: -> { 'CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP' }
end
end
end
Comments
In my approach, I add NOT NULL constraint to columns i need in my existing migrated migration. After that, I reset all my migrations by using this command:
rake db:migrate:reset
This will drop the database, create it again and run all the migrations. You can check your changes in schema.rb.
If you have few columns in simple migrations, you can use this approach.
Comments
If need simultaneously change NOT NULL constraints in the table in single query, use change_null table definition:
change_table :table_name, bulk: true do |t|
t.change_null :first_column_name, false
t.change_null :second_column_name, true
end
It will generate such SQL:
ALTER TABLE table_name
ALTER COLUMN first_column_name SET NOT NULL,
ALTER COLUMN second_column_name DROP NOT NULL;
If pass extra argument:
t.change_null :third_column_name, false, '123'
It will add UPDATE query:
UPDATE table_name
SET third_column_name = '123'
WHERE third_column_name IS NULL;