我正在开发 Ruby on Rails 应用程序。我们正在使用 PostgreSQL 数据库。
有一个名为
scores
的表,其中包含以下列:
Column | Type
--------------+-----------------------
id | integer
value | double precision
ran_at | timestamp
active | boolean
build_id | bigint
metric_id | integer
platform_id | integer
mode_id | integer
machine_id | integer
higher_better | boolean
job_id | integer
variation_id | integer
step | character varying(255)
我需要向job_id
添加一个
序列(注意:
job
没有模型)。
如何创建这个序列?
CREATE SEQUENCE
:
CREATE SEQUENCE scores_job_id_seq; -- = default name for plain a serial
然后添加一列默认值到
scores.job_id
:
ALTER TABLE scores ALTER COLUMN job_id
SET DEFAULT nextval('scores_job_id_seq');
要将序列“绑定”到列(因此当删除列时它也会被删除),还运行:
ALTER SEQUENCE scores_job_id_seq OWNED BY scores.job_id;
所有这些都可以替换为首先使用列 serial
的伪数据类型
job_id
。参见:
如果您的表格已有行,您可能需要将
SEQUENCE
设置为当前最大值:
SELECT setval('scores_job_id_seq', COALESCE(max(job_id), 1)) FROM scores;
唯一剩下的区别:
serial
列也设置为NOT NULL
。你可能也想要那个。如果存在任何空值,请首先使用序列值更新:
UPDATE scores
SET job_id = nextval('scores_job_id_seq')
WHERE job_id IS NULL;
最后:
ALTER TABLE scores ALTER COLUMN job_id SET NOT NULL;
相关:
但是你不能只改变现有
integer
的类型:
ALTER TABLE scores ALTER job_id TYPE serial;
serial
不是实际的数据类型。这只是 CREATE TABLE
的一个符号化便利功能。IDENTITY
列:
所以我想出了如何在 Ruby on Rails 上使用 ActiveRecord 迁移来做到这一点。我基本上使用了 Erwin 的命令和此页面的帮助,并将它们放入迁移文件中。这些是步骤:
1. 在终端中输入:
rails g migration CreateJobIdSequence
rails g migration AddJobIdSequenceToScores
2. 编辑迁移文件如下:
20140709181616_create_job_id_sequence.rb:
class CreateJobIdSequence < ActiveRecord::Migration
def up
execute <<-SQL
CREATE SEQUENCE job_id_seq;
SQL
end
def down
execute <<-SQL
DROP SEQUENCE job_id_seq;
SQL
end
end
20140709182313_add_job_id_sequence_to_scores.rb:
class AddJobIdSequenceToScores < ActiveRecord::Migration
def up
execute <<-SQL
ALTER SEQUENCE job_id_seq OWNED BY scores.job_id;
ALTER TABLE scores ALTER COLUMN job_id SET DEFAULT nextval('job_id_seq');
SQL
end
def down
execute <<-SQL
ALTER SEQUENCE job_id_seq OWNED BY NONE;
ALTER TABLE scores ALTER COLUMN job_id SET NOT NULL;
SQL
end
end
3. 迁移数据库。在终端中输入:
rake db:migrate