【问题标题】:Set Primary Key value 0 and auto increment on Migration PostgreSQL在 Migration PostgreSQL 上设置主键值 0 并自动递增
【发布时间】:2012-08-28 17:33:35
【问题描述】:

我有一个包含 2 个字段的模型 => :name 和 :age

我需要做一个迁移,添加一列 :position 需要自动递增并从 0(零)开始。

我试过这些方法:

class AddPosition < ActiveRecord::Migration
  def up
    add_column :clientes, :position, :integer, :default => 0, :null => false
    execute "ALTER TABLE clientes ADD PRIMARY KEY (position);"
  end

但它不起作用,因为它不会自动递增。如果我尝试使用主键作为类型:

class AddPosition < ActiveRecord::Migration
  def up
    add_column :clientes, :position, :primary_key, :default => 0, :null => false
  end
end

rake db:migrate 不运行,因为有多个值。

任何人都可以解释一种在带有 Rails 3.2 的主键上设置零和自动增量的方法吗?

【问题讨论】:

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


    【解决方案1】:

    在 PostgreSQL 中设置自动递增列的方法如下:

    # in migration:
    def up
      execute <<-SQL
        CREATE SEQUENCE clients_position_seq START WITH 0 MINVALUE 0;
        ALTER TABLE clients ADD COLUMN position INTEGER NOT NULL DEFAULT nextval('clients_position_seq');
      SQL
    end
    

    但不幸的是,它可能不是您所需要的。如果您使用如下 SQL 将值插入到 clients 表中,上述方法将起作用:INSERT INTO clients(name, age) VALUES('Joe', 21),而 rails 不能以这种方式工作。

    第一个问题是 rails 期望主键被称为id。虽然您可以覆盖此约定,但它会导致比它解决的问题更多的问题。如果要将位置绑定到主键值,更好的选择是向模型添加虚拟属性,方法如下:

    def position
      id.nil? ? nil : id - 1
    end
    

    但是假设您已经拥有常规主键 id 并且想要添加 position 字段,以便您可以在创建客户端后重新排序客户端,无需触摸他们的 ID(这总是一个好主意)。第二个问题来了:rails 不会识别和尊重DEFAULT nextval('clients_position_seq'),即它不会从 PG 支持的序列中提取值,并且默认情况下会尝试将NULL 放入position

    我建议将acts_as_list gem 视为更好的选择。这将使数据库序列操作变得不必要。不幸的是,它使用1 作为position 的初始值,但这可以通过设置列表位置字段的自定义名称和定义方法来解决,如上所示。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-12-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-09-02
      • 1970-01-01
      • 2021-01-19
      • 1970-01-01
      相关资源
      最近更新 更多