【问题标题】:rails3 bigint primary keyrails3 bigint 主键
【发布时间】:2011-08-18 07:44:24
【问题描述】:

我想在 Rails 3 下创建一个bigint(或string 或任何不是int)类型的主键字段。

我有一个给定的数据结构,例如:

things
------
id bigint primary_key
name char(32)

我目前正在尝试推动的方法:

create_table :things, :id => false do |t| # That prevents the creation of (id int) PK
  t.integer :id, :limit => 8 # That makes the column type bigint
  t.string :name, :limit => 32
  t.primary_key :id # This is perfectly ignored :-(
end

列类型将是正确的,但主键选项不会出现在 sqlite3 中,我怀疑 MySQL 也是这种情况。

【问题讨论】:

    标签: ruby-on-rails ruby-on-rails-3 primary-key bigint


    【解决方案1】:

    不久前自己有过这个问题并在这里找到了答案:Using Rails, how can I set my primary key to not be an integer-typed column?

    您需要设置primary_key: false,然后在执行迁移之前使用自定义语句。

    编辑 1:您需要检查您的数据库文档以了解要执行的确切查询。它作为常规 SQL 语句执行,并且需要特定于数据库。我提到的问题中的示例是针对 Postgre SQL 的。如果您使用的是 MySQL,则可能需要更改它。

    【讨论】:

    • ALTER TABLE things ADD PRIMARY KEY (id);:这是在所有数据库上运行的东西吗?
    • 我可以在迁移时为此编写一个 case-when 结构吗?我可以在那里测试数据库变体吗?
    • 我相信你可以,但我不知道怎么做。你可以改用 Rails.env 吗?
    • self.upself.connection.adapter_name。请参阅ActiveRecord::ConnectionAdapters::AbstractAdapter 的文档。感谢您的帮助!
    【解决方案2】:

    我遇到了同样的问题。我认为最简单的表格方法

    accounts 
    id bigint primary key 
    name char 

    create_table :accounts do |t|
    t.string :name
    end
    change_column :accounts, :id , "bigint NOT NULL AUTO_INCREMENT"

    【讨论】:

    • 快到了。就做change_column :accounts, :id, 'bigint'
    • 如果你只使用'bigint',你会失去自动增量
    • @skalogirou 我刚刚做了change_column :my_primary, :id, 'bigint' 并且工作正常,没有失去自动增量(在 Rails 4,Postgres 上)
    • 在 MySQL/MariaDB 中,如果你只使用 'bigint' 你将失去自动增量
    【解决方案3】:

    对于 MySQL,您可以使用“SERIAL”,它是“BIGINT UNSIGNED NOT NULL AUTO_INCREMENT”的别名

    class ChangeUserIdToBigint < ActiveRecord::Migration
      def change
        change_column :users, :id, 'SERIAL'
      end
    end
    

    【讨论】:

    • 你说得对,SERIAL 的显着区别在于它还向该列添加了一个 unique 键索引。
    【解决方案4】:

    skalogirou's answer 很好,但更改不会反映在 schema.rb 中。所以像db:schema:loaddb:test:clone 这样的任务不会创建相同的数据库结构。

    所需的解决方法是增强db:schema:load 和 db:test:clone rake 任务,如下所述: http://www.lshift.net/blog/2013/09/30/changing-the-primary-key-type-in-ruby-on-rails-models/

    这是我基于该解决方法使用的:

    namespace :my_app do
      namespace :db do
        task :after_schema_load_and_db_test_clone => :environment do
        puts 'Changing primary key for :my_table'
        query = 'ALTER TABLE <my_table> CHANGE id id bigint DEFAULT NULL auto_increment'
        ActiveRecord::Base.connection.execute(query)
      end
    end
    
    
    Rake::Task['db:schema:load'].enhance do
      ::Rake::Task['my_app:db:after_schema_load_and_db_test_clone'].invoke
    end
    
    Rake::Task['db:test:clone'].enhance do
      ::Rake::Task['my_app:db:after_schema_load_and_db_test_clone'].invoke
    end
    

    【讨论】:

    • 我发现切换到 SQL 转储更容易:config.active_record.schema_format = :sql in config/application.rb。
    【解决方案5】:

    如果你想转换 Postgres 中的所有表,你需要运行这段代码

    class ConvertIntToBigint < ActiveRecord::Migration[5.1]
      def up
        query = <<-SQL
          SELECT tablename AS "tablename"
          FROM pg_tables
          WHERE schemaname = 'public';
        SQL
        connection.execute(query).each do |element|
          if column_exists?(element['tablename'], :id, :integer)
            change_table(element['tablename']) {|t| t.change :id, :bigint }
          end
        end
      end
    
      def down
      end
    end
    

    【讨论】:

      【解决方案6】:

      对于那些来到这里(就像我一样)努力弄清楚如何制作使用bigint 而不是int 的自定义id 列的人,我没有意识到的是Rails 5.1 及以上版本,bigintid 的默认类型

      https://github.com/rails/rails/pull/26266

      【讨论】:

      • 注意,尽管 Rails 5.1 为主键列设置了默认值 bigint,但它是 signed,而不是 unsigned。要设置默认的 unsigned,请查看这个 Github 问题并在那里表示您的支持:github.com/rails/rails/issues/40967
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-10-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-09-14
      • 1970-01-01
      相关资源
      最近更新 更多