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?
Asked
Active
Viewed 6.8k times
5 Answers
303
You can also use change_column_null:
change_column_null :table_name, :column_name, false

nates
- 8,312
- 5
- 32
- 28
-
1I had to change it for a bunch of columns and this doesn't require specifying the column type for each column, much better! – Dorian Jan 08 '15 at 12:19
-
1This is the better answer. In my database, I was adding a null constraint on a column with pre-existing null values. change_column would not update those values. Per the documentation, change_column_null has an optional fourth value which is the new value for the update. – Merovex Jan 01 '16 at 05:22
-
1interesting side effect.... rolling back the migration will set the field to the opposite (false -> true). So if you create the migration for several fields to add a null constraint, and some fields ALREADY had a null constraint, then rollback the migration, it will REMOVE the null constraint from any field that already had it. – jpw Jan 16 '19 at 18:50
-
1The forth option will set the default value for those entries, where the column is null indeed. **But be carefull!** It can cause **downtime** if it's a big table. Better first to backfill those records in batches, and then add a constraint without forth option. – user2992971 Sep 06 '19 at 14:44
97
For Rails 4+, nates' answer (using change_column_null) is better.
Pre-Rails 4, try change_column.

Dan Wich
- 4,923
- 1
- 26
- 22
-
27Be careful with this approach -- if you had other attributes about that column (for example a `: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_null` – Nathan Wallace Mar 09 '15 at 15:51
-
Note that this generates an `IrreversibleMigration` which may not be what you want. – Nic Nilov Feb 17 '17 at 14:30
-
-
@Mark I was talking about the answer, sorry for not being specific enough. – Nic Nilov Dec 28 '17 at 20:03
-
12
Add column with default value
Remove default value
add_column :orders, :items, :integer, null: false, default: 0
change_column :orders, :items, :integer, default: nil

Rafael Tavares
- 5,678
- 4
- 32
- 48

rndrfero
- 312
- 2
- 6
-
2this is correct solution when you need to add new column that is not null, you need to first define that it has default value because SQLLite will complain (Cannot add a NOT NULL column with default value NULL), and then remove it! – Milan Feb 01 '17 at 22:32
3
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

Manjunath Reddy
- 1,039
- 2
- 13
- 22
0
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.

Dharman
- 30,962
- 25
- 85
- 135

Thien Ngan
- 96
- 1
- 6