rails3 bigint primary key

て烟熏妆下的殇ゞ 提交于 2019-11-27 06:48:43

问题


I would like to create a bigint (or string or whatever that is not int) typed primary key field under Rails 3.

I have a given structure of data, for example:

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

The approach I'm currently trying to push:

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

The column type will be correct, but the primary key option will not be present with sqlite3 and I suspect that this is the case for MySQL too.


回答1:


Had that myself not long ago and found the answer here: Using Rails, how can I set my primary key to not be an integer-typed column?

You need to set primary_key: false and then use a custom statement before you execute the migration.

EDIT 1: You need to check your database docs for the exact query to perform. It is executed as a regular SQL statement and needs to be database specific. The example in the question I referred to is for Postgre SQL. If you are on MySQL you might have to change that.




回答2:


I had the same problem. I think the easiest way for a table

accounts 
id bigint primary key 
name char 

is

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



回答3:


For MySQL you can use "SERIAL" which is alias for "BIGINT UNSIGNED NOT NULL AUTO_INCREMENT"

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



回答4:


skalogirou's answer is good but the change will not be reflected in schema.rb. So the tasks like db:schema:load and db:test:clone will not create identical DB structure.

The required workaround is to enhance db:schema:load and db:test:clone rake tasks as described here: http://www.lshift.net/blog/2013/09/30/changing-the-primary-key-type-in-ruby-on-rails-models/

This is what I used based on that workaround:

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



回答5:


If you want to convert all tables in Postgres you will need to run this code

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


来源:https://stackoverflow.com/questions/5880207/rails3-bigint-primary-key

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!