【问题标题】:How to allow NULL value for one column in unique index on multiple columns如何在多列的唯一索引中允许一列的 NULL 值
【发布时间】:2014-03-05 10:42:53
【问题描述】:

似乎是一个非常简单的问题,但我似乎无法在网上的任何地方找到具体答案。

我有一个 price 模型,它同时引用了报价和订单项,因此它有 quote_idline_item_id 列。我正在使用带有unique: true 的多列索引来防止将同一line_item 的多个价格附加到报价中。 quote_id 是索引中的第一列。

但是,我希望允许用户向line_items 添加尚未报价的价格。它适用于一个价格,quote_id 为空,line_item_id 存在。但是,唯一索引阻止我将第二个价格附加到相同的line_itemquote_id 中的空值被视为唯一。

有没有办法让唯一约束仅在引号不为空时适用?
我知道allow_nil可以在模型验证中使用,但是可以在索引中使用吗?

我在想这样的事情:

add_index :prices, [:quote_id, :line_item_id], :unique => true, :allow_nil => true

PostgreSQL 和 Rails 4.

【问题讨论】:

  • 感谢您的链接 - 不知道我是如何错过这个问题的。所以看来我不需要:allow_nil,但问题出在列的顺序上。如果我将 :line_item_id 放在索引中的 :quote_id 之前,它应该允许我要查找的内容,即多个相同的 line_item_ids,quote_id 为 NULL。

标签: sql ruby-on-rails postgresql indexing unique-constraint


【解决方案1】:

有没有办法让唯一约束只在引号不为空时适用?

其实这是唯一方式。您可以拥有多个“相同”条目,其中多列索引中的一个或多个列是 NULL,因为 Postgres 不会为此目的考虑两个相同的 NULL 值(就像在大多数情况下一样)。

索引中的列顺序与此无关。 (It matters for other purposes, though.)

确保表本身中的基础列可以是NULL。 (有时会与空字符串 '' 混淆。)

重新阅读您的问题后,更合适的场景似乎是这个相关的答案:
Create a multicolumn index to enforce uniqueness
这个问题也可能有帮助,但问题要求您的相反
How to add a conditional unique index on PostgreSQL

如果你真的想要一个只有非空值的partial index,你也可以这样做:

CREATE INDEX price_uni_idx ON price (quote_id, line_item_id)
WHERE  quote_id     IS NOT NULL
AND    line_item_id IS NOT NULL;

不过,您需要以达到您的目的。从索引中排除具有 NULL 值的行以使其更快可能仍然有用。详情看这里:
Indexed ORDER BY with LIMIT 1

【讨论】:

  • 谢谢 - 这正是我需要的答案。我能够让它正常工作。
猜你喜欢
  • 2017-05-19
  • 1970-01-01
  • 2013-03-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-03-14
相关资源
最近更新 更多