【问题标题】:Ruby on Rails creating migration to reverse UUID primary keysRuby on Rails 创建迁移以反转 UUID 主键
【发布时间】:2021-10-16 04:35:16
【问题描述】:

我目前正在编写代码以将我们的数据库默认 ID 列转换为 UUID 格式。

我的迁移代码示例是

def up
      remove_reference :examples, :user, null: false, foreign_key: true
      add_column :users, :uuid, :uuid, default: "gen_random_uuid()", null: false
      change_table :users do |t|
        t.remove :id, type: :id
        t.rename :uuid, :id
      end
      execute "ALTER TABLE users ADD PRIMARY KEY (id);"
      add_reference :examples, :user, null: false, foreign_key: true, type: :uuid
    end

基本上这允许我将我的 ID 列转换为 UUID 格式。

我创建了一个向下函数,以便能够回滚,但由于此错误而失败 ERROR: column "user_id" of relationship "examples" contains null values

我意识到会有一个问题,因为一旦数据库中有数据,它将无法回滚并再次创建正确的引用。有人对我应该如何处理我的向下功能有任何想法吗?

def down
      remove_reference :examples, :user, null: false, foreign_key: true, type: :uuid

      execute 'ALTER TABLE users DROP CONSTRAINT users_pkey'
      add_column :users, :new_id, :primary_key

      change_table :users do |t|
        t.remove :id, type: :uuid
        t.rename :new_id, :id
      end

      add_reference :examples, :user, null: false, foreign_key: true
    end

有人对我应该如何进行此操作有任何建议吗?原来的迁移是在一个变更函数中,但由于执行块而无法回滚。

【问题讨论】:

    标签: ruby-on-rails postgresql rails-activerecord


    【解决方案1】:

    一次性进行此类数据库更改时要小心。我建议你分成几个步骤。

    第一步(新列 uuid)

    • 为 uuid 创建新列
    def up
          add_column :users, :uuid, :uuid, default: "gen_random_uuid()", null: false
          add_column :examples, :user_uuid, :uuid
    end
    

    调整您的代码以使用最近创建的列填充examples.user_uuid 列;您可以通过创建模型回调轻松实现此目的,自动感受user_uuid

    如果您的数据库有 GB 的数据,请考虑将 uuid 添加为可为空,并使用队列或批量填充列。新记录将已被填写。

    我们现在有两个新列,新数据正在提交并全部同步

    第二步(重命名)

    一旦填充并使用新列,就可以重命名列并关联新键了。

    def up
          change_table :examples do |t|
            t.rename :user_id, type: :old_user_id
            t.rename :user_uuid, :user_id
          end
          
          change_table :users do |t|
            t.rename :id, type: :old_id
            t.rename :uuid, :id
          end
    
          execute "ALTER TABLE users ADD PRIMARY KEY (id);"
          add_reference :examples, :user, null: false, foreign_key: true, type: :uuid
        end
    
    def down
    # ...
    end
    
    

    请记住删除或查看之前更改的模型代码,以支持此新列或忽略。

    现在我们已经更改了列,但没有丢失旧的参考。

    这里要小心,如果你的数据库很大,你可能会锁定你的操作。也许您可能需要一个维护窗口。

    第三步(删除旧列)

    现在我们可以删除旧列,一切正常


    注意:在对数据库进行此类更改时始终要小心。执行这样的事情是非常危险的。如果要继续,请模拟多次重命名步骤。在执行之前制作数据库快照,并通知您的客户您的服务可能会停机。

    我不知道你为什么要将主键更改为uuid,这对数据库进行查询和连接数据的成本很高。比较UUID 比比较integer 更复杂。考虑在您的表中创建一个新的索引列 uuid 并让数据库加入并基于此字段。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多