如何定义在 Rails 5.2 上的 Ruby ActiveRecord 迁移中创建 table 时使用的序列?
How to define the sequence to use when creating a table in ActiveRecord migration in Ruby on Rails 5.2?
我需要为我的 table 的 ID 字段分配一个特定的 Postgres 序列。在模型中,我尝试定义以下对 Posgres 没有影响的设置:
class MyObject < ActiveRecord::Base
self.sequence_name = "global_seq"
通常,ActiveRecord 迁移中的 table 定义以
开头
create_table "objects", id: :serial, force: :cascade do |t|
生成列默认值的 Postgres 定义为
default nextval('objects_id_seq'::regclass)
如何在迁移中指定 nextval() 函数应依赖于另一个序列?
恐怕 Rails' 迁移没有内置命令来显式设置列的顺序。它非常特定于数据库。
但是可以使用普通 SQL:
class ChangeSequenceOfObjectId < ActiveRecord::Migration[5.0]
def self.up
execute <<-SQL
CREATE SEQUENCE global_seq;
ALTER TABLE objects ALTER COLUMN id SET DEFAULT nextval('global_seq');
ALTER SEQUENCE objects_id_seq OWNED BY NONE;
ALTER SEQUENCE global_seq OWNED BY objects.id;
SQL
end
def self.down
execute <<-SQL
ALTER TABLE objects ALTER COLUMN id SET DEFAULT nextval('objects_id_seq');
ALTER SEQUENCE objects_id_seq OWNED BY objects.id;
ALTER SEQUENCE global_seq OWNED BY NONE;
DROP SEQUENCE global_seq;
SQL
end
如果 global_seq
序列是在其他迁移中创建的,则只需删除有关其创建/删除的相应行。
如果您想将 global_sql
序列保留为 'free-standing',也可以删除 ALTER SEQUENCE global_seq OWNED BY
命令(即使 objects
table 保留在数据库中下降)。
您可以在迁移中更改默认值:
change_column :my_objects, :id, :integer, default: -> { "nextval('global_seq')" }
您可能希望使用 :bigint
而不是 :integer
,具体取决于序列和表格的设置方式。您必须对 :default
选项使用 lambda 才能将原始 nextval('global_seq')
表达式导入数据库。
您可能还想删除旧序列,据我所知,您必须为此使用 connection.execute('drop sequence ...')
。
如果您跳过 create_table
中的默认 :id
步骤,那么您可以在手动创建 :id
列时完成所有操作:
create_table :my_objects, id: false do |t|
t.bigint :id, null: false, default: -> { "nextval('global_seq')" }
t.primary_key :id
...
end
同样,t.bigint
和 t.integer
之间的选择取决于您希望 PK 有多大。
我使用 sequence_name
选项 (Rails 5.1):
create_table "opjects", sequence_name: 'global_seq' do |t|
我没有检查,但我想,在 Rails 5.2 中它应该也可以。
我需要为我的 table 的 ID 字段分配一个特定的 Postgres 序列。在模型中,我尝试定义以下对 Posgres 没有影响的设置:
class MyObject < ActiveRecord::Base
self.sequence_name = "global_seq"
通常,ActiveRecord 迁移中的 table 定义以
开头create_table "objects", id: :serial, force: :cascade do |t|
生成列默认值的 Postgres 定义为
default nextval('objects_id_seq'::regclass)
如何在迁移中指定 nextval() 函数应依赖于另一个序列?
恐怕 Rails' 迁移没有内置命令来显式设置列的顺序。它非常特定于数据库。
但是可以使用普通 SQL:
class ChangeSequenceOfObjectId < ActiveRecord::Migration[5.0]
def self.up
execute <<-SQL
CREATE SEQUENCE global_seq;
ALTER TABLE objects ALTER COLUMN id SET DEFAULT nextval('global_seq');
ALTER SEQUENCE objects_id_seq OWNED BY NONE;
ALTER SEQUENCE global_seq OWNED BY objects.id;
SQL
end
def self.down
execute <<-SQL
ALTER TABLE objects ALTER COLUMN id SET DEFAULT nextval('objects_id_seq');
ALTER SEQUENCE objects_id_seq OWNED BY objects.id;
ALTER SEQUENCE global_seq OWNED BY NONE;
DROP SEQUENCE global_seq;
SQL
end
如果 global_seq
序列是在其他迁移中创建的,则只需删除有关其创建/删除的相应行。
如果您想将 global_sql
序列保留为 'free-standing',也可以删除 ALTER SEQUENCE global_seq OWNED BY
命令(即使 objects
table 保留在数据库中下降)。
您可以在迁移中更改默认值:
change_column :my_objects, :id, :integer, default: -> { "nextval('global_seq')" }
您可能希望使用 :bigint
而不是 :integer
,具体取决于序列和表格的设置方式。您必须对 :default
选项使用 lambda 才能将原始 nextval('global_seq')
表达式导入数据库。
您可能还想删除旧序列,据我所知,您必须为此使用 connection.execute('drop sequence ...')
。
如果您跳过 create_table
中的默认 :id
步骤,那么您可以在手动创建 :id
列时完成所有操作:
create_table :my_objects, id: false do |t|
t.bigint :id, null: false, default: -> { "nextval('global_seq')" }
t.primary_key :id
...
end
同样,t.bigint
和 t.integer
之间的选择取决于您希望 PK 有多大。
我使用 sequence_name
选项 (Rails 5.1):
create_table "opjects", sequence_name: 'global_seq' do |t|
我没有检查,但我想,在 Rails 5.2 中它应该也可以。