如何在Postgresql查询中使用多个“唯一索引推断”
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何在Postgresql查询中使用多个“唯一索引推断”相关的知识,希望对你有一定的参考价值。
在Postgresql 9.6 DB中,有一个名为X
的现有表有四列,a
,b
,c
和d
,索引设置如下:
"uidx_a_b" UNIQUE, btree (a, b) WHERE c IS NULL AND d IS NULL
"uidx_a_c" UNIQUE, btree (a, b, c) WHERE c IS NOT NULL AND d IS NULL
"uidx_a_d" UNIQUE, btree (a, b, c, d) WHERE c IS NOT NULL AND d IS NOT NULL
我不知道为什么要这样做,因为它是由一个早已离去的人在我不得不修改它之前完成的。
我试图让语法正确,以便在ON CONFLICT语句中指定所有这三个。我尝试了所有错误的变化。 Postgresql Documentation表明这是可能的,特别是在[, ...]
中描述的conflict_target
:
( { index_column_name | ( index_expression ) } [ COLLATE collation ] [ opclass ] [, ...] )
此外,来自其中一位提交者的blog也这么说。最后,我再次看着this unit test for the functionality无济于事!因此放弃了,我转向SO寻求帮助。
这是我认为最接近我应该工作的语法:
ON CONFLICT (
((a, b) WHERE c IS NULL AND d IS NULL),
((a, b, c) WHERE c IS NOT NULL AND d IS NULL),
((a, b, c, d) WHERE release_id IS NOT NULL AND d IS NOT NULL)
)
然而,这失败了:
ERROR: syntax error at or near ","
虽然我愿意提出改进这些索引的design
的建议,但我真的想知道是否有一个有效的语法来指定ON CONFLICT子句,因为它似乎应该存在!
在下面我指的是the documentation的语法描述:
ON CONFLICT [ conflict_target ] conflict_action
其中
conflict_target
可以是以下之一:
( { index_column_name | ( index_expression ) }
[ COLLATE collation ] [ opclass ] [, ...] ) [ WHERE index_predicate ]
ON CONSTRAINT constraint_name
INSERT ... ON CONFLICT
只允许一个conflict_target
。 [, ...]
意味着可以指定多个列或表达式(表示单个条件),如下所示:
ON CONFLICT (col1, (col2::text), col3)
此外,如果它是一个部分指数,WHERE
条件必须由index_predicate
暗示。
所以,你可以做什么?
您可以按照@joop的建议找到c
和d
列中不会出现的值。
然后您可以用以下内容替换三个索引:
CREATE UNIQUE INDEX ON x (a, b, coalesce(c, -1), coalesce(d, -1));
然后conflict_target
将成为:
ON CONFLICT (a, b, coalesce(c, -1), coalesce(d, -1))
以上是关于如何在Postgresql查询中使用多个“唯一索引推断”的主要内容,如果未能解决你的问题,请参考以下文章