创建多列索引以强制实现唯一性

时间:2013-09-20 11:33:43

标签: sql postgresql null indexing unique-index

我的桌子上有两个字段,如果它们(邋and和暗淡)相等,我就丢弃它们,即

id| tat | dim | visible
1 | 11  | 22  | true
2 | 11  | 22  | false

这被认为不是ids 12的有效输入。因为我希望每个dim允许一个tat。所以我有一个脚本为我清理了这些重复项,之后我在这个表上添加了索引以防止这种情况发生:

CREATE UNIQUE INDEX dim_tat_idx
ON predictions (tat, dim);

正如在这个答案中非常好地解释的那样:

https://stackoverflow.com/a/8918141/169277

在这种情况下现在进一步

This way you can enter (1,2), (1,3) and (1, NULL)
but neither of them a second time

我将创建哪种类型的索引或在数据库级别使用哪种其他机制来允许输入1, NULL组合,但多次阻止(1,2)(1,3)

1 个答案:

答案 0 :(得分:2)

这似乎是一种误解。

我的答案中的引用有点误导,因为它只适用于你在那里创建额外的部分索引时: How to add a conditional unique index on PostgreSQL

如果你没有添加第二个索引(就像你没有那样),你已经有了解决方案,那就好了。仅使用多列唯一索引,您可以多次输入(1, NULL),但只能输入(1,2)(1,3)一次。

空字符串

如果您错误地考虑空字符串('')(对于character type)而不是NULL值:那些处理方式与其他任何值一样。您可以使用多列,部分功能唯一索引index on an expression)来处理这种情况:

CREATE UNIQUE INDEX predictions _dim_tat_uni_idx
ON predictions (tat, NULLIF(dim, ''));

这样您只能输入一次(1, 'a')(1, 'b')(1, NULL)(1, '')多次。

副作用

索引仍然完全支持第一列(tat)上的普通查询 但是两列上的查询都必须匹配表达式才能充分发挥潜力。这会更快,即使它似乎没有意义:

SELECT * FROM predictions
WHERE  tat = 1
AND    NULLIF(dim, '') = 'foo';

..比这个:

SELECT * FROM predictions
WHERE  tat = 1
AND    dim = 'foo';

..因为第一个查询可以使用两个索引列。结果将是相同的(搜索''NULL时除外)。 Details in this related answer on dba.SE