40

如何更改 ActiveRecord 的 ID 的(默认)类型?int 不够长,我更喜欢 long。我很惊讶没有 :long 用于迁移 - 只是使用一些小数吗?

4

11 回答 11

49

归功于http://moeffju.net/blog/using-bigint-columns-in-rails-migrations

class CreateDemo < ActiveRecord::Migration
  def self.up
    create_table :demo, :id => false do |t|
      t.integer :id, :limit => 8
    end
  end
end
  • 请参阅:id => false禁用自动创建 id 字段的选项
  • t.integer :id, :limit => 8行将生成一个 64 位整数字段
于 2011-05-03T13:25:26.167 回答
44

要设置默认的主键列类型,迁移文件不是乱七八糟的地方。

相反,只需将其粘贴在您的底部config/environment.rb

ActiveRecord::ConnectionAdapters::MysqlAdapter::NATIVE_DATABASE_TYPES[:primary_key] = "BIGINT UNSIGNED DEFAULT NULL auto_increment PRIMARY KEY"

并且您的所有表都应该使用预期的列类型创建id

+--------------+---------------------+------+-----+---------+----------------+
| Field        | Type                | Null | Key | Default | Extra          |
+--------------+---------------------+------+-----+---------+----------------+
| id           | bigint(20) unsigned | NO   | PRI | NULL    | auto_increment | 

在你完成了你打算做的事情之后......下一个问题可能是“如何使我的外键列具有相同的列类型?” 因为将主键设置people.idbigint(20) unsigned, 和person_idbeint(11)或其他任何东西没有意义?

对于这些列,您可以参考其他建议,例如

t.column :author_id, 'BIGINT UNSIGNED'
t.integer :author_id, :limit => 8

更新:@Notinlist,要在任意表上使用任意列作为主键,您需要这样做create_table-change_column

create_table(:users) do |t|
  # column definitions here..
end
change_column :users, :id, :float # or some other column type

例如,如果我想要guid而不是自动递增整数,

create_table(:users, :primary_key => 'guid') do |t|
  # column definitions here..
end
change_column :users, :guid, :string, :limit => 36
于 2009-09-18T03:09:35.973 回答
7

这很难通过迁移为主键设置,因为 Rails 会自动将其放入。

您可以稍后更改任何列,如下所示:

change_column :foobars, :something_id, 'bigint'

您可以在初始迁移中将非主 ID 指定为自定义类型,如下所示:

create_table :tweets do |t|
  t.column :twitter_id, 'bigint'
  t.column :twitter_in_reply_to_status_id, 'bigint'
end

在我有“bigint”的地方,您可以放置​​您的数据库将用于您想要使用的数据库列类型的任何文本(例如,“unsigned long”)。

如果您需要将 id 列设为 bigint,最简单的方法是创建表,然后使用 change_column 在同一迁移中更改列。

使用 PostgreSQL 和 SQLite,模式更改是原子的,因此如果迁移失败,这不会使您的数据库处于奇怪的状态。使用 MySQL,您需要更加小心。

于 2009-07-01T05:51:24.770 回答
6

根据 Rails API 文档,类型的可能选项是:

:string
:text
:integer
:float
:decimal
:datetime
:timestamp
:time
:date
:binary
:boolean

您可以使用 :decimal,也可以根据需要直接执行命令:

class MyMigration
  def self.up
    execute "ALTER TABLE my_table ADD id LONG"
  end
end

正如 wappos 所指出的,您可以使用 :limit 之类的辅助选项来告诉 ActiveRecord 您希望该列有多大。因此,您将使用具有更大 :limit 的 :int 列。

于 2009-06-30T22:19:27.740 回答
5

如果有人需要它来使用 PostgreSQL,请创建一个像这样的初始化程序:

# config/initializers/bigint_primary_keys.rb
ActiveRecord::Base.establish_connection
ActiveRecord::ConnectionAdapters::PostgreSQLAdapter::NATIVE_DATABASE_TYPES[:primary_key] = 'bigserial primary key'

由于 Rails 3.2(甚至更早的版本)中的延迟加载,在ActiveRecord::ConnectionAdapters::PostgreSQLAdapter您建立数据库连接之前不需要。

于 2012-08-20T20:30:17.417 回答
4

rails4,你可以做到。

以下是在&中创建Dummy模型的示例,rails4postgres

xxx_migrate_dummies.rb:

class CreateDummies < ActiveRecord::Migration
  def change
    create_table :dummies, :id => false do |t|
      t.column :id, :serial8, primary_key: true
      t.string :name, :limit => 50, null: false
      t.integer :size, null: false

      t.column :create_date, :timestamptz, null: false
    end
  end
end

它做了什么:

  • serial8用作 id 类型,为 64 位整数,并将其定义为primary key.
  • timestamptz用作包含时区信息的日期时间类型,这对于跨越多个时区的应用程序很重要。
于 2015-10-16T13:24:28.477 回答
2

导轨 3,MySQL:

t.column :foobar, :int, :limit => 8

不给我一个 bigint,只有一个 int。然而,

t.column :twitter_id, 'bigint'

工作正常。(尽管它确实将我与 MySQL 联系在一起。)

于 2011-01-15T06:26:30.733 回答
2

借鉴其他解决方案,针对最近对我有用的方法进行了调整。

添加到config/initializers. 它声明了一个新的列类型(改编自 chookeat 的建议)。

ActiveRecord::ConnectionAdapters::Mysql2Adapter::NATIVE_DATABASE_TYPES[:long_primary_key] = "BIGINT(20) DEFAULT NULL auto_increment PRIMARY KEY"

使用长 id 的迁移如下:

    create_table :notification_logs, :id => false do |t|

      t.column :id, :long_primary_key
      # ...
    end
于 2012-08-08T15:37:51.870 回答
0

我编写了一个名为activerecord-native_db_types_override的 gem ,它可以让您更改将在迁移中使用的数据类型。

在您的 Gemfile 中,添加:

gem 'activerecord-native_db_types_override'

然后在 config/environment.rb 中,要在 postgres 中使用长 id,请添加:

NativeDbTypesOverride.configure({
  postgres: {
    primary_key: { name: "bigserial primary key"}
  }
})

有关最新信息,请参阅其自述文件。

于 2013-01-11T20:25:06.633 回答
0

你可以这样做:

class CreateUsers < ActiveRecord::Migration[5.0]
  def change
    create_table :users, id: :bigserial do |t|
      t.string :name
    end
  end
end
于 2016-12-28T13:38:09.680 回答
-1

更正如何更改默认primary key列类型:

代替:

ActiveRecord::ConnectionAdapters::MysqlAdapter::NATIVE_DATABASE_TYPES[:primary_key] = "BIGINT UNSIGNED DEFAULT NULL auto_increment PRIMARY KEY"

你应该做:

ActiveRecord::ConnectionAdapters::MysqlAdapter::NATIVE_DATABASE_TYPES[:primary_key] = "BIGINT(8) UNSIGNED DEFAULT NULL auto_increment PRIMARY KEY"

否则您将无法foreign key在数据库层中添加限制。

于 2013-02-25T13:13:56.530 回答