如何更改 ActiveRecord 的 ID 的(默认)类型?int 不够长,我更喜欢 long。我很惊讶没有 :long 用于迁移 - 只是使用一些小数吗?
11 回答
归功于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 位整数字段
要设置默认的主键列类型,迁移文件不是乱七八糟的地方。
相反,只需将其粘贴在您的底部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.id
为bigint(20) unsigned
, 和person_id
beint(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
这很难通过迁移为主键设置,因为 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,您需要更加小心。
根据 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 列。
如果有人需要它来使用 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
您建立数据库连接之前不需要。
中rails4
,你可以做到。
以下是在&中创建Dummy
模型的示例,rails4
postgres
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
用作包含时区信息的日期时间类型,这对于跨越多个时区的应用程序很重要。
导轨 3,MySQL:
t.column :foobar, :int, :limit => 8
不给我一个 bigint,只有一个 int。然而,
t.column :twitter_id, 'bigint'
工作正常。(尽管它确实将我与 MySQL 联系在一起。)
借鉴其他解决方案,针对最近对我有用的方法进行了调整。
添加到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
我编写了一个名为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"}
}
})
有关最新信息,请参阅其自述文件。
你可以这样做:
class CreateUsers < ActiveRecord::Migration[5.0]
def change
create_table :users, id: :bigserial do |t|
t.string :name
end
end
end
更正如何更改默认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
在数据库层中添加限制。