How to write SQL in a migration in Rails

SqlPostgresqlRuby on-Rails-3MigrationRails Activerecord

Sql Problem Overview


I have the following SQL which I need to do

CREATE TABLE cars_users2 AS SELECT DISTINCT * FROM cars_users;

DROP TABLE cars_users;

ALTER TABLE cars_users2 RENAME TO cars_users;

since I cannot use heroku dataclips to drop a table, I cannot use dataclips.

So I guess I need to do this in a migration.

How do I write this sql as a migration?

Sql Solutions


Solution 1 - Sql

For your up migration:

execute "CREATE TABLE cars_users2 AS SELECT DISTINCT * FROM cars_users;" 
drop_table :car_users  
rename_table :car_users2, :car_users  

and for down:

raise ActiveRecord::IrreversibleMigration

Full migration:

class TheMigration < ActiveRecord::Migration
	def up
		execute "CREATE TABLE cars_users2 AS SELECT DISTINCT * from cars_users;" 
		drop_table :car_users  
		rename_table :car_users2, :car_users  
	end

	def down
		raise ActiveRecord::IrreversibleMigration
	end
end

Solution 2 - Sql

You could try to use the execute method.

Something like this (it's untested, some kind of brainchild)

class UpdateCarUserTable < ActiveRecord::Migration
  def up
    execute "CREATE TABLE cars_users2 AS SELECT DISTINCT * FROM cars_users"
    execute "DROP TABLE cars_users"
    execute "ALTER TABLE cars_users2 RENAME TO cars_users"
  end

As there is no equivalent down method, an ActiveRecord::IrreversibleMigration should be raised when trying to migrate down.

Solution 3 - Sql

I prefer here doc:

execute <<-SQL
  CREATE TABLE cars_users2 AS SELECT DISTINCT * FROM cars_users;
  DROP TABLE cars_users;
  ALTER TABLE cars_users2 RENAME TO cars_users;
SQL

notice: This only works for PostgreSQL, if you are using MySQL you should set CLIENT_MULTI_STATEMENTS for the adapter.

Solution 4 - Sql

In case you need to use change instead of up and down you can use reversible. It works on Rails 4 or above.

class ExampleMigration < ActiveRecord::Migration
  def change
    create_table :distributors do |t|
      t.string :zipcode
    end
 
    reversible do |dir|
      dir.up do
        # add a CHECK constraint
        execute <<-SQL
          ALTER TABLE distributors
            ADD CONSTRAINT zipchk
              CHECK (char_length(zipcode) = 5) NO INHERIT;
        SQL
      end
      dir.down do
        execute <<-SQL
          ALTER TABLE distributors
            DROP CONSTRAINT zipchk
        SQL
      end
    end
 
    add_column :users, :home_page_url, :string
    rename_column :users, :email, :email_address
  end
end

Sources: http://edgeguides.rubyonrails.org/active_record_migrations.html#using-reversible

https://apidock.com/rails/ActiveRecord/Migration/reversible

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionNick GinantoView Question on Stackoverflow
Solution 1 - SqlTomdarknessView Answer on Stackoverflow
Solution 2 - SqlConcurrentHashMapView Answer on Stackoverflow
Solution 3 - SqlfangxingView Answer on Stackoverflow
Solution 4 - SqlJoão Paulo MottaView Answer on Stackoverflow