验证多列的唯一性

Posted

技术标签:

【中文标题】验证多列的唯一性【英文标题】:Validate uniqueness of multiple columns 【发布时间】:2011-06-19 17:58:29 【问题描述】:

是否有一种方法可以验证实际记录是唯一的,而不仅仅是一列?例如,一个友谊模型/表不应该有多个相同的记录,例如:

user_id: 10 | friend_id: 20
user_id: 10 | friend_id: 20

【问题讨论】:

尝试在您的模型中使用“validates_uniqueness_of”。如果这不起作用,请尝试创建一个索引,您可以在该索引上创建 feilds 迁移,其中包括 add_index :table, [:column_a, :column_b], :unique => true) 之类的语句 不幸的是,validates :field_name, unique: true 容易出现竞争条件,因此即使反对 rails-way,实际约束也是首选。 @HarryJoy 我会赞成一个描述约束方式的答案。 @Green 公平地说,这是确保它永远不会发生的好方法。可以绕过验证。 比下面提到的更好的答案是***.com/a/34425284/1612469,因为它带来了另一层以确保一切正常 【参考方案1】:

您可以按如下方式确定validates_uniqueness_of 调用的范围。

validates_uniqueness_of :user_id, :scope => :friend_id

【讨论】:

只是想补充一点,您可以传递多个范围参数,以防您需要验证超过 2 个字段的唯一性。 IE。 :scope => [:friend_id, :group_id] 奇怪的是你不能说validates_uniqueness_of [:user_id, :friend_id]。也许这需要修补? Alexey, validates_uniqueness_of [:user_id, :friend_id] 只会对列出的每个字段进行验证 - 并且记录在案和预期的行为 在 Rails 4 中,这变成: validates :user_id, uniqueness: scope: :friend_id 您可能想添加一个自定义错误消息,例如 :message => ' has already this friend.'【参考方案2】:

您可以使用validates 在一列上验证uniqueness

validates :user_id, uniqueness: scope: :friend_id

多列验证的语法类似,但您应该提供一个字段数组:

validates :attr, uniqueness: scope: [:attr1, ... , :attrn]

然而,上面显示的验证方法存在竞争条件,无法确保一致性。考虑以下示例:

    数据库表记录在n个字段中应该是唯一的;

    多个(两个或更多)并发请求,分别由单独的进程(应用程序服务器、后台工作服务器或您正在使用的任何东西)处理,访问数据库在表中插入相同的记录;

    每个进程并行验证是否存在具有相同n个字段的记录;

    每个请求的验证都成功通过,每个进程在表中创建一条数据相同的记录。

为避免这种行为,应向 db 表添加一个唯一约束。您可以通过运行以下迁移为一个(或多个)字段使用 add_index 助手设置它:

class AddUniqueConstraints < ActiveRecord::Migration
  def change
   add_index :table_name, [:field1, ... , :fieldn], unique: true
  end
end

警告:即使您设置了唯一约束,两个或多个并发请求也会尝试将相同的数据写入 db,但不会创建重复记录,而是会引发 @987654323 @ 异常,应该单独处理:

begin
# writing to database
rescue ActiveRecord::RecordNotUnique => e
# handling the case when record already exists
end 

【讨论】:

【参考方案3】:

这可以通过对两列的数据库约束来完成:

add_index :friendships, [:user_id, :friend_id], unique: true

您可以使用 rails 验证器,但通常我建议使用数据库约束。

更多阅读:https://robots.thoughtbot.com/validation-database-constraint-or-both

【讨论】:

以上是关于验证多列的唯一性的主要内容,如果未能解决你的问题,请参考以下文章

Laravel 4:多列的独特验证

CoreData(IOS)多列的唯一约束?

MySQL处理重复键错误插入具有多个唯一索引的表;不是多列唯一索引

我们可以在 MS 访问数据库上创建多列唯一索引吗?

多列的唯一约束

数据库表索引:普通索引唯一性索引全文索引多列索引隐藏索引删除索引