【问题标题】:Rails Migration Create Table Primary KeyRails 迁移创建表主键
【发布时间】:2011-01-22 18:31:36
【问题描述】:

我正在编写一个迁移脚本来创建一个主键列名为guid 并且是VARCHAR(25) 的表。问题是我觉得我必须加倍努力才能一步到位。

如果我跑:

create_table(:global_feeds, :primary_key => 'guid') do |t|
  t.string :guid, :limit => 25
  t.text :title
  t.text :subtitle

  ...

  t.timestamps
end

我得到一个主键名为guid 的表,没有名为id 的列(这是我想要的)。但是,问题是 guid 列是 INT(11) 并启用了自动增量。所以我必须运行一个额外的命令:

change_column :global_feeds, :guid, :string, :limit => 25

似乎有点令人费解,必须基本上运行两个 SQL 命令才能获得我认为应该在一个命令中实现的功能。

关于如何优化这个有什么建议吗?

【问题讨论】:

    标签: mysql optimization ruby-on-rails-3 migration


    【解决方案1】:

    在 Rails 4 中你可以这样做;

    create_table :global_feeds, id: false do |t|
      t.string :guid, primary_key: true
     ...
    end
    

    【讨论】:

    • 这不应该是字符串,带有uuid的mysql应该是二进制(16)
    【解决方案2】:

    我想你正在使用 mySQL,所以这里是你可以尝试的方法

    create_table :global_feeds, {:id => false} do |t|
      t.string :guid
      t.text :title
      t.text :subtitle
      t.timestamps
    end
    execute "ALTER TABLE global_feeds ADD PRIMARY KEY (guid);"
    

    如果您不在 mySQL 上,您应该更改 execute 命令中的查询以在您的数据库引擎上工作。我不确定你是否可以在 SQLite 上做到这一点。并且不要忘记将此行放在 global_feed.rb 模型中的某个位置:

    set_primary_key :guid
    

    不管怎样,您在遵守 Rails 惯例的同时,也能充分利用 Rails。更改主键名称和类型可能不是一个好主意。

    【讨论】:

    • 不幸的是,这仍然是两个和我一样的 SQL 语句。您刚刚颠倒了操作顺序:首先定义列类型,然后指定主键。
    • 我猜你不能在一次操作中做到这一点,但我想这没有什么问题。对于更复杂的情况,迁移有两个语句是完全可以的。
    • 我也不确定 ActiveRecord 是否可以正常使用非整数主键。
    • 我将投票给你,只是为了 maxt3r 的努力。感谢您的尝试。
    • 我在处理我继承的架构时遇到了这个问题;我使用primary_key 以及此问题和其他相关问题中的大多数其他建议尝试了几乎所有可能的组合。在带有 MySQL 的 Rails 3.2.x 上,这个解决方案是可行的。需要注意的一个关键问题:rake db:schema:dump 不会产生所需的输出(db:structure:dump 可以)。呼应@MaxAlFarakh 的 cmets:更改主键名称和类型,这不是一个好主意:-|
    【解决方案3】:

    您需要使用#column 而不是#string。例如:

    create_table(:global_feeds, :primary_key => 'guid') do |t|
      t.column :guid, "varchar(25)", :null => false
      ...
    end
    

    请注意,varchar 类型不可移植到 MySQL 以外的数据库。

    【讨论】:

    • syntax error, unexpected '(', expecting keyword_end t.column :guid, :varchar(26), :null => false 指向varchar末尾的括号
    • 没错。使用"varchar(25)" 而不是:varchar(25)
    • 您也可以只使用 :string 类型并将 limit: 25 设置为此示例的选项。
    【解决方案4】:

    这在 Rails 3 中是可能的。尝试:

      def self.up
        create_table(:signups, :id => false) do |t|
          t.string :token, :primary => true
    

    查看此要点,了解使用 UUID 作为主键 col 的绝佳解决方案:https://gist.github.com/937739

    【讨论】:

    • 查看@kakoni 的回答
    【解决方案5】:

    在 Rails 5 中,对于在 rails db:setup 从 @kakoni 迁移时遇到问题 ArgumentError: Index name '*' on table '*' already exists 的人,以下对我有用

    create_table(:global_feeds, primary_key: :guid, id: false) do |t|
      t.string :guid
     ...
    end
    

    更多信息,请查看create_table

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-10-16
      • 2023-03-19
      • 1970-01-01
      • 1970-01-01
      • 2011-03-19
      • 2014-05-30
      • 2012-10-01
      相关资源
      最近更新 更多