【问题标题】:adding auto-incrementing column in active record在活动记录中添加自动递增列
【发布时间】:2014-07-20 13:43:40
【问题描述】:

我正在尝试在我的 postgresql 表中添加一个基于整数的自动递增列,然后通过活动记录访问它。它不断被活动记录设置为 NULL。

明显的方法:

add_column :table_name, :id_name, :primary_key

这不起作用,因为表已经有一个主键。

接下来我尝试将其添加到 Active Record 迁移的上游部分:

execute("ALTER TABLE table_name ADD id_name SERIAL;")

这在创建表时非常有效,如果我通过数据库直接创建一个新条目,id_name 会按照人们的希望设置。但是,如果我使用 .new & .save 或 .create 通过 ActiveRecord 创建一个新条目,它会在尝试将 id_name 设置为 null 时爆炸。

我也试过了:

execute("CREATE SEQUENCE table_name_id_name_seq;")
execute("ALTER TABLE table_name ADD id_name INTEGER DEFAULT NEXTVAL('table_name_id_name_seq');")
execute("ALTER SEQUENCE table_name_id_name_seq OWNED BY table_name.id_name;")

这允许 .new & .save 以及 .create 进行条目,但结果的 id_name 为 null。

有什么方法可以说服 Rails 不要用 null 覆盖默认的 db 值?

【问题讨论】:

  • 你看过 gem "sequenced" (github.com/djreimer/sequenced)。完全符合您的要求...
  • 通过 PG gem 添加条目会导致 id_name 设置正确,只要我通过 DEFAULT 而不是 null。
  • @Danny 感谢您的链接 - 浏览它。如果可能的话,我希望增量发生在 db 层。
  • @Danny 这对新行很有用,但是所有旧行都保留为空。我需要做一些事情,在表中的每一行(包括新行)上创建 id。不过还是谢谢你。这几乎是一个解决方案!

标签: ruby-on-rails postgresql activerecord


【解决方案1】:

这有点 hacky,但这里有一个可行的解决方案:

def up   
  add_column :table_name, :id_name, :integer
  n = 1
  TableName.all.each_with_index do |name|
    name.id_name = n
    name.save
    n += 1
  end
  execute "CREATE SEQUENCE table_name_id_name_seq START #{n} OWNED BY table_name.id_name;"
end


def next_seq_value(sequence)
  Article.connection.execute("SELECT nextval('#{sequence}')")[0]['nextval']
end


before_validation(:on => :create) do
  unless attribute_present?("id_name")
    self.id_name = next_seq_value('table_name_id_name_seq')
  end
 end

【讨论】:

    【解决方案2】:

    使用类型 serial 让数据库自动增加列的问题在于 schema.db 不支持它,因此例如,您将无法让该功能填充测试数据库。

    相反,这是一种支持递增列的与数据库无关的方式:

      before_create :increment_identifier
    
      def increment_identifier
        sql = "SELECT COALESCE(MAX(identifier), 0) + 1 FROM claims"
        self.identifier = ActiveRecord::Base.connection.execute(sql).values[0][0]
      end
    

    COALESCE 只是为空表返回 0 而不是 nil。而values[0][0] 是访问 ActiveRecord.Base 返回的时髦对象的必要方法。

    【讨论】:

    • 这个解决方案的问题是它与并行请求不兼容。这是一个逻辑回调,而不是直接在请求的数据库排序过程中排队的物理回调。
    猜你喜欢
    • 2018-05-25
    • 2015-04-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-10-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多