似乎是一个非常直截了当的问题,但我似乎无法在网上任何地方找到具体答案。
我有一个引用引号和订单项的price
模型,因此它有quote_id
和line_item_id
列。我使用带有unique: true
的多列索引来防止将同一line_item的多个价格附加到报价。 quote_id
是索引中的第一列。
但是,我想允许用户将价格添加到未引用的line_items
。只需一个价格即可正常工作,quote_id
为空且line_item_id
存在。但是,唯一索引阻止我将第二个价格附加到同一line_item
。 quote_id
中的空值被视为唯一。
有没有办法让这个唯一约束仅在引用不为空时才适用?
我知道allow_nil
可以用于模型验证,但它可以在索引中使用吗?
我想的是:
add_index :prices, [:quote_id, :line_item_id], :unique => true, :allow_nil => true
PostgreSQL和Rails 4。
答案 0 :(得分:2)
有什么方法可以使这个唯一约束仅在引用不为空时应用?
实际上,这是 唯一的方式。您可以拥有多个“相同”条目,多列索引中的一个或多个列为NULL
,因为Postgres不会为此目的考虑两个NULL
值相同(如在大多数情况下)。 / p>
索引中的列序列对此无关紧要。 (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