【问题标题】:Creating a PostgreSQL sequence to a field (which is not the ID of the record)为字段创建 PostgreSQL 序列(不是记录的 ID)
【发布时间】:2014-08-30 17:10:42
【问题描述】:

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

如何创建这个序列?

【问题讨论】:

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


    【解决方案1】:

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

    可选:

    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的类型:

    <strike>ALTER TABLE scores ALTER job_id TYPE serial;</strike>

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

    【讨论】:

    【解决方案2】:

    所以我想出了如何在 Ruby on Rails 上使用 ActiveRecord 迁移来做到这一点。我基本上使用了 Erwin 的命令和来自this page 的帮助,并将它们放入迁移文件中。这些是步骤:

    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
    

    【讨论】:

    • 如果你想要一个字符串作为job_id,只需使用to_char(nextval('job_id_seq'), 'JB000000') 而不是nextval('job_id_seq')
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-01-18
    • 1970-01-01
    • 1970-01-01
    • 2018-02-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多