首页 > 解决方案 > activerecord 对多条记录的唯一约束

问题描述

我应该如何编写 activerecord 迁移来反映这一点:

CREATE TABLE table (
    c1 data_type,
    c2 data_type,
    c3 data_type,
    UNIQUE (c2, c3)
);

会在一列上添加唯一约束,但我正在寻找的是在 2 列的组合上创建唯一约束,如在多列上创建唯一约束部分中所述。

编辑

更准确地说:我有一个表帐户和一个表 balance_previous_month。

class CreateBalance < ActiveRecord::Migration[6.1]
  def change    
        create_table :balance_previous_month do |t|
        t.decimal :amount, :precision => 8, :scale => 2
        t.date :value_date
        t.belongs_to :account, foreign_key: true
        t.timestamps
    end
  end
end

由于我们在 1 月,起息日(即上个月月底的余额)为2020-12-31.

我想对表 balance_previous_month 设置一个约束,其中 peraccount_id只能value_date有一个给定数量。金额可以更新,但给定帐户不能有 2 个相同的 value_dates。

标签: postgresqlactiverecordunique-constraint

解决方案


您添加到另一篇文章的链接并不完全等同于您的请求,因为一个答案谈到通过模型强制执行唯一性,而另一个谈到在您的示例中使用约束时使用索引。(检查以获取有关它们之间差异的更多信息)。

有两个地方可以强制执行唯一性,即应用程序和数据库,也可以同时在两个地方完成。

数据库

所以如果你想通过使用索引来强制唯一性,你可以使用这个:

def change
  add_index :table, [:c2, :c3], unique: true
end

如果要像示例中那样添加约束,则必须在迁移中运行直接 sql 查询,因为 rails 中没有内置方法可以做到这一点。

def up
  execute <<-SQL
    ALTER TABLE table
    ADD UNIQUE (c2, c3)
  SQL
end

检查上面的链接以获取有关它们之间差异的更多信息。

应用

通过模型强制执行唯一性:

validates :c2, uniqueness: { scope: :c3 }

推荐阅读