rails3 bigint主键

时间:2011-05-04 07:46:59

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

我想在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也是如此。

5 个答案:

答案 0 :(得分:3)

不久前我自己就找到了答案:Using Rails, how can I set my primary key to not be an integer-typed column?

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

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

答案 1 :(得分:3)

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

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

答案 2 :(得分:0)

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

答案 3 :(得分:0)

如果要转换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

答案 4 :(得分:0)

对于那些像我一样来这里的人来说,是为了弄清楚如何制作一个使用id而不是bigint的自定义int列,没有意识到对于Rails 5.1及更高版本,bigintid的默认类型

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