How might you clone a database table via Rails migration?

12,704

Solution 1

Try doing it with pure SQL. This will do what you want:

CREATE TABLE new_tbl LIKE orig_tbl;

Solution 2

In Rails 4 & PostgreSQL, create a new migration and insert:

ActiveRecord::Base.connection.execute("CREATE TABLE clone_table_name AS SELECT * FROM source_table_name;")

This will create the clone with the exact structure of the original table, and populate the new table with old values.

More info: http://www.postgresql.org/docs/9.0/static/sql-createtableas.html

Solution 3

This will do. It's not perfect, because it won't copy table options or indices. If you do have any table options set, you will have to add them to this migration manually.

To copy indices you'll have to formulate a SQL query to select them, and then process them into new add_index directives. That's a little beyond my knowledge. But this works for copying the structure.

class CopyTableSchema < ActiveRecord::Migration
  def self.up
    create_table :new_models do |t|
      Model.columns.each do |column|
        next if column.name == "id"   # already created by create_table
        t.send(column.type.to_sym, column.name.to_sym,  :null => column.null, 
          :limit => column.limit, :default => column.default, :scale => column.scale,
          :precision => column.precision)
      end
    end

    # copy data 

    Model.all.each do |m|
      NewModel.create m.attributes
    end
  end

  def self.down
    drop_table :new_models
  end
end

Solution 4

Copy the tables entry from your projects db/schema.rb straight into your migration. Just change the table name and your good to go.

Share:
12,704

Related videos on Youtube

Teflon Ted
Author by

Teflon Ted

Married to Java. Sleeping with Ruby.

Updated on April 15, 2022

Comments

  • Teflon Ted
    Teflon Ted about 2 years

    I want a migration to create a clone of an existing table by just suffixing the name, including all the indexes from the original table.

    So there's a "snapshots" table and I want to create "snapshots_temp" as an exact copy of the table (not the data, just the table schema, but including the indexes).

    I could just copy and paste the block out of the schema.rb file and manually rename it.

    But I'm not sure by the time this migration is applied if the definition from schema.rb will still be accurate. Another developer might have changed the table and I don't want to have to update my migration script.

    So how might I get the schema of the table at runtime? Essentially, how does 'rake schema:dump' reverse engineer the table so I can do the same in my migration? (but changing the table name).

  • Teflon Ted
    Teflon Ted over 14 years
    > it won't copy table options or indices Thanks but indexes is a requirement.
  • Teflon Ted
    Teflon Ted over 14 years
    Good call. "Use LIKE to create an empty table based on the definition of another table, including any column attributes and indexes defined in the original table" dev.mysql.com/doc/refman/5.1/en/create-table.html
  • MiniQuark
    MiniQuark almost 14 years
    Works with MySQL (and possibly most databases) but if you use Sqlite, it won't work. I ran into this problem in development environment. Production is fine (it's MySQL).
  • Rich Sutton
    Rich Sutton over 11 years
    Awesome thanks. Note that your copied table will get the indexes, but not any foreign keys. You'll have to recreate those separately.
  • Rescribet
    Rescribet almost 10 years
    For those on PostgreSQL: CREATE TABLE new_tbl (LIKE orig_tbl INCLUDING DEFAULTS INCLUDING INDEXES); or INCLUDING ALL to clone everything
  • Guillermo Siliceo Trueba
    Guillermo Siliceo Trueba about 9 years
    Careful with this as it will copy the ID column too and it won't set it as primary in the new table.
  • Excalibur
    Excalibur about 9 years
    Here's a useful answer in another post for the two commands to clone and copy all data into another table: stackoverflow.com/a/3280042/513739
  • Thomas Andrews
    Thomas Andrews over 6 years
    And it won't recreated indices.
  • wuliwong
    wuliwong over 5 years
    could you explain how to use that in the migration?
  • David Bodow
    David Bodow almost 5 years
    Will this properly synchronize with schema.rb? EDIT - Answering my own question: yes -- stackoverflow.com/questions/3815447/…
  • Subham Padhi
    Subham Padhi over 3 years
    Lol I wanted something that clones without index