Postgres唯一的约束忽略空值但Rails通过

时间:2018-06-12 09:27:37

标签: ruby-on-rails postgresql

我的postgres数据库中有一个唯一的索引participations就像这样

"participation_uniqueness" UNIQUE, btree (event_id, firstname, lastname, email)

这很有效,除非其中一个字段为零,它基本上被忽略了:

  

event_id |名字|姓氏|电子邮件   
1982 |约翰| Doe | john@doe.de   
1982 |汉斯| Doe | john@doe.de   
1982 | null | null | john@doe.de   
1982 | null | null | john@doe.de

如果值为null,我也希望应用唯一性约束,因此上面的示例表中的最后一条记录不可能,因为它针对唯一约束。

在Rails中,我可以简单地将其作为验证方法添加到我的模型中

validates_uniqueness_of :email, scope: [:event_id, :firstname, :lastname]

我想知道为什么这个验证正在考虑NULL进行唯一性检查,但SQL没有?

研究这个主题我理解它是SQL标准,因为NULL被解释为“缺少信息”,你无法将丢失的信息相互比较。

但从逻辑的角度来看,这对我来说毫无意义。我希望在这种情况下DB插入失败。如果不实现此处发布的脏解决方法,我怎样才能实现这一目标 https://www.pgrs.net/2008/01/11/postgresql-allows-duplicate-nulls-in-unique-columns/

1 个答案:

答案 0 :(得分:1)

使用部分索引有可能的答案here

CREATE UNIQUE INDEX ab_c_null_idx ON my_table (a, b) WHERE c IS NULL;

Rails的行为有所不同,因为它在uniqueness validator中做了更多。它不只是运行查询。