为字段创建PostgreSQL序列(不是记录的ID)

时间:2014-07-09 15:26:03

标签: ruby-on-rails postgresql activerecord rails-activerecord rails-postgresql

我正在开发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没有模型)。

如何创建此序列?

2 个答案:

答案 0 :(得分:29)

使用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;

所有这些都可以替换为使用job_id列的伪数据类型serial开头:

如果您的表已有行,您可能需要将SEQUENCE设置为下一个最高值,并在表格中填写缺少的序列值:

SELECT setval('scores_job_id_seq', COALESCE(max(job_id), 1)) FROM scores;

任选地:

UPDATE scores
SET    job_id = nextval('scores_job_id_seq')
WHERE  job_id IS NULL;

唯一剩下的差异,serial列也设置为NOT NULL。您可能也可能不想这样:

ALTER TABLE scores ALTER COLUMN job_id SET NOT NULL;

无法只改变现有integer的类型:

ALTER TABLE scores ALTER job_id TYPE serial;

serial不是实际的数据类型。它只是CREATE TABLE的符号便利功能 在Postgres 10或更高版本中,请考虑IDENTITY列:

答案 1 :(得分:15)

所以我想出了如何使用Ruby on Rails上的ActiveRecord迁移来实现这一点。我基本上使用了this page的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