---
title: "Rails 6 adds if_not_exists option to create_table"
description: "Rails 6 adds if_not_exists option to create_table"
canonical_url: "https://www.bigbinary.com/blog/rails-6-adds-if_not_exists-option-to-create_table"
markdown_url: "https://www.bigbinary.com/blog/rails-6-adds-if_not_exists-option-to-create_table.md"
---

# Rails 6 adds if_not_exists option to create_table

Rails 6 adds if_not_exists option to create_table

- Author: Amit Choudhary
- Published: May 22, 2019
- Categories: Rails 6, Rails

Rails 6 added [if_not_exists](https://github.com/rails/rails/pull/31382) to
[create_table](https://api.rubyonrails.org/v5.2/classes/ActiveRecord/ConnectionAdapters/SchemaStatements.html#method-i-create_table)
option to create a table if it doesn't exist.

Before Rails 6, we could use
[ActiveRecord::Base.connection.table_exists?](https://api.rubyonrails.org/v5.2/classes/ActiveRecord/ConnectionAdapters/SchemaStatements.html#method-i-table_exists-3F).

Default value of [if_not_exists](https://github.com/rails/rails/pull/31382)
option is `false`.

#### Rails 5.2

Let's create `users` table in Rails 5.2.

```ruby
>> class CreateUsers < ActiveRecord::Migration[6.0]
>>   def change
>>     create_table :users do |t|
>>       t.string :name, index: { unique: true }
>>
>>       t.timestamps
>>     end
>>   end
>> end

>> CreateUsers.new.change
-- create_table(:users)
CREATE TABLE "users" ("id" bigserial primary key, "name" character varying, "created_at" timestamp NOT NULL, "updated_at" timestamp NOT NULL)

=> #<PG::Result:0x00007fd73e711cf0 status=PGRES_COMMAND_OK ntuples=0 nfields=0 cmd_tuples=0>
```

Now let's try creating `users` table again with
[if_not_exists](https://github.com/rails/rails/pull/31382) option.

```ruby
>> class CreateUsers < ActiveRecord::Migration[6.0]
>>   def change
>>     create_table :users, if_not_exists: true do |t|
>>       t.string :name, index: { unique: true }
>>
>>       t.timestamps
>>     end
>>   end
>> end

>> CreateUsers.new.change
-- create_table(:users, {:if_not_exists=>true})
CREATE TABLE "users" ("id" bigserial primary key, "name" character varying, "created_at" timestamp NOT NULL, "updated_at" timestamp NOT NULL)

=> Traceback (most recent call last):
        2: from (irb):121
        1: from (irb):114:in 'change'
ActiveRecord::StatementInvalid (PG::DuplicateTable: ERROR:  relation "users" already exists)
: CREATE TABLE "users" ("id" bigserial primary key, "name" character varying, "created_at" timestamp NOT NULL, "updated_at" timestamp NOT NULL)
```

We can see that Rails 5.2 ignored
[if_not_exists](https://github.com/rails/rails/pull/31382) option and tried
creating the table again.

Now let's try
[ActiveRecord::Base.connection.table_exists?](https://api.rubyonrails.org/v5.2/classes/ActiveRecord/ConnectionAdapters/SchemaStatements.html#method-i-table_exists-3F)
with Rails 5.2.

```ruby
>> class CreateUsers < ActiveRecord::Migration[5.2]
>>   def change
>>     unless ActiveRecord::Base.connection.table_exists?('users')
>>       create_table :users do |t|
>>         t.string :name
>>
>>         t.timestamps
>>       end
>>     end
>>   end
>> end

>> CreateUsers.new.change

=> nil
```

We can see that `create_table :users` never executed because
`ActiveRecord::Base.connection.table_exists?('users')` returned true.

#### Rails 6.0.0.beta2

Let's create `users` table in Rails 6 with
[if_not_exists](https://github.com/rails/rails/pull/31382) option set as true.

```ruby
>> class CreateUsers < ActiveRecord::Migration[6.0]
>>   def change
>>     create_table :users, if_not_exists: true do |t|
>>       t.string :name, index: { unique: true }
>>
>>       t.timestamps
>>     end
>>   end
>> end

>> CreateUsers.new.change
-- create_table(:users, {:if_not_exists=>true})
CREATE TABLE IF NOT EXISTS "users" ("id" bigserial primary key, "name" character varying, "created_at" timestamp(6) NOT NULL, "updated_at" timestamp(6) NOT NULL)

=> #<PG::Result:0x00007fc4614fef48 status=PGRES_COMMAND_OK ntuples=0 nfields=0 cmd_tuples=0>

>> CreateUsers.new.change
-- create_table(:users, {:if_not_exists=>true})
CREATE TABLE IF NOT EXISTS "users" ("id" bigserial primary key, "name" character varying, "created_at" timestamp(6) NOT NULL, "updated_at" timestamp(6) NOT NULL)

=> #<PG::Result:0x00007fc46513fde0 status=PGRES_COMMAND_OK ntuples=0 nfields=0 cmd_tuples=0>
```

We can see that no exception was raised when we tried creating `users` table the
second time.

Now let's see what happens if we set
[if_not_exists](https://github.com/rails/rails/pull/31382) to false.

```ruby
>> class CreateUsers < ActiveRecord::Migration[6.0]
>>   def change
>>     create_table :users, if_not_exists: false do |t|
>>       t.string :name, index: { unique: true }
>>
>>       t.timestamps
>>     end
>>   end
>> end

>> CreateUsers.new.change
-- create_table(:users, {:if_not_exists=>false})
CREATE TABLE "users" ("id" bigserial primary key, "name" character varying, "created_at" timestamp(6) NOT NULL, "updated_at" timestamp(6) NOT NULL)

=> Traceback (most recent call last):
        2: from (irb):23
        1: from (irb):15:in `change'
ActiveRecord::StatementInvalid (PG::DuplicateTable: ERROR:  relation "users" already exists
)
```

As we can see, Rails raised an exception here because
[if_not_exists](https://github.com/rails/rails/pull/31382) was set to false.

Here is the relevant [pull request](https://github.com/rails/rails/pull/31382).

## Links

- [Human page](https://www.bigbinary.com/blog/rails-6-adds-if_not_exists-option-to-create_table)
