Rails 4.将表id迁移到UUID

Der*_*153 18 migration ruby-on-rails rails-migrations

我有一个表: db/migrate/20140731201801_create_voc_brands.rb:

class CreateVocBrands < ActiveRecord::Migration
  def change
    create_table :voc_brands do |t|
      t.string :name

      t.timestamps
    end
  end
end
Run Code Online (Sandbox Code Playgroud)

但我需要将表更改为此(如果我将从零创建它):

class CreateVocBrands < ActiveRecord::Migration
  def change
    create_table :voc_brands, :id => false do |t|
      t.uuid :id, :primary_key => true
      t.string :name

      t.timestamps
    end
    add_index :voc_brands, :id
  end
end
Run Code Online (Sandbox Code Playgroud)

如何使用迁移更改此设置?

小智 32

我和你的问题一样.要从默认ID迁移到使用uuid,我认为你可以使用类似于我的东西:

class ChangeVocBrandsPrimaryKey < ActiveRecord::Migration
  def change
    add_column :voc_brands, :uuid, :uuid, default: "uuid_generate_v4()", null: false

    change_table :voc_brands do |t|
      t.remove :id
      t.rename :uuid, :id
    end
    execute "ALTER TABLE voc_brands ADD PRIMARY KEY (id);"
  end
end
Run Code Online (Sandbox Code Playgroud)

  • 解决方案适用于这种情况,因为voc_brands表没有数据,否则它可能会破坏数据,尤其是在voc_brands具有依赖性的情况下. (6认同)
  • 这可行,但我必须将 `add_column` 默认声明的格式更新为 `default: -&gt; { "gen_random_uuid()" }` (3认同)

小智 5

我知道迁移是进行任何数据库更改的首选方式,但以下方法很棒。可以使用对 PostgreSQL 的直接查询来转换具有现有数据的表。

对于主键:

    ALTER TABLE students
        ALTER COLUMN id DROP DEFAULT,
        ALTER COLUMN id SET DATA TYPE UUID USING (uuid(lpad(replace(text(id),'-',''), 32, '0'))),
        ALTER COLUMN id SET DEFAULT uuid_generate_v4()
Run Code Online (Sandbox Code Playgroud)

对于其他参考:

    ALTER TABLE students
        ALTER COLUMN city_id SET DATA TYPE UUID USING (uuid(lpad(replace(text(city_id),'-',''), 32, '0')))
Run Code Online (Sandbox Code Playgroud)

左上方用零填充整数值并转换为 UUID。这种方法不需要 id 映射,如果需要,可以检索旧 id。

由于没有数据复制,这种方法工作得非常快。

要处理这些和更复杂的多态关联情况,请使用https://github.com/kreatio-sw/webdack-uuid_migration。这个 gem 向 ActiveRecord::Migration 添加了额外的帮助程序以简化这些迁移。

  • 我知道这是一年中最好的部分,但我回来的唯一目的是为您在 https://github.com/kreatio-sw/webdack-uuid_migration 上引用 gem 点赞。我发现了一个外键引用的问题,并在今天提交了一个 PR,并且可以说即使在 5.2.0.alpha 版本的 rails 上它也运行得很好!几个月前,我们尝试手工做同样的事情,这非常痛苦。感谢分享!+1 (3认同)