我需要为表的ID字段分配一个特定的Postgres序列。在模型中,我尝试定义以下对Posgres没有影响的设置:
MyObject类
self.sequence_name =“ global_seq”
通常,ActiveRecord迁移中的表定义以
开始create_table "objects", id: :serial, force: :cascade do |t|
生成Postgres列默认值的定义为
default nextval('objects_id_seq'::regclass)
如何在迁移中指定nextval()函数应依赖另一个序列?
答案 0 :(得分:3)
您可以在迁移中更改默认设置:
change_column :my_objects, :id, :integer, default: -> { "nextval('global_seq')" }
您可能希望使用:bigint
而不是:integer
,具体取决于顺序和表的设置方式。您必须对:default
选项使用lambda才能将原始nextval('global_seq')
表达式获取到数据库中。
您可能还希望删除旧序列,因此您必须使用connection.execute('drop sequence ...')
。
如果您跳过:id
中的默认create_table
步骤,则可以在手动创建: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的大小。
答案 1 :(得分:1)
恐怕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
序列,则只需删除有关其创建/删除的相应行即可。
如果您想将ALTER SEQUENCE global_seq OWNED BY
序列保留为“独立式”(即使删除了global_sql
表,也可以保留在db中),也可以删除objects
命令。
答案 2 :(得分:0)
我使用sequence_name
选项(Rails 5.1):
create_table "opjects", sequence_name: 'global_seq' do |t|
我没有检查,但是我猜想,在Rails 5.2中也应该起作用。