很容易模仿像
这样的唯一约束create table foo(x int, exclude (x with =));
但是如何使用IS NOT DISTINCT FROM
代替=
(因此表中只有一个NULL
值?)
创建f(anyelement, anyelement)
之类的函数并且运算符失败,因为null
具有未知类型。还有一个问题:是否可以将IS NOT DISTINCT FROM
谓词包装到PostgreSQL中的运算符中?
要有耐心,我不是在寻找替代解决方案,我知道很多:)
答案 0 :(得分:3)
很容易创建一个与NOT DISTINCT TO
对应的函数和运算符:
CREATE FUNCTION ndist(anyelement, anyelement) RETURNS boolean
IMMUTABLE CALLED ON NULL INPUT LANGUAGE sql
AS 'SELECT $1 IS NOT DISTINCT FROM $2';
CREATE OPERATOR === (
PROCEDURE = ndist,
LEFTARG = anyelement,
RIGHTARG = anyelement,
COMMUTATOR = "==="
);
如果两个参数都是无类型的NULL,则会失败:
test=> SELECT NULL === NULL;
ERROR: could not determine polymorphic type because input has type unknown
一种解决方案是使用重载并为您需要的每种类型定义相同的函数和运算符:
CREATE FUNCTION ndist(integer, integer) RETURNS boolean
IMMUTABLE CALLED ON NULL INPUT LANGUAGE sql
AS 'SELECT $1 IS NOT DISTINCT FROM $2';
CREATE FUNCTION ndist(text, text) RETURNS boolean
IMMUTABLE CALLED ON NULL INPUT LANGUAGE sql
AS 'SELECT $1 IS NOT DISTINCT FROM $2';
CREATE OPERATOR === (
PROCEDURE = ndist,
LEFTARG = integer,
RIGHTARG = integer,
COMMUTATOR = "==="
);
CREATE OPERATOR === (
PROCEDURE = ndist,
LEFTARG = text,
RIGHTARG = text,
COMMUTATOR = "==="
);
然后该示例将起作用:
test=> SELECT NULL === NULL;
?column?
----------
t
(1 row)
这是因为在这种情况下,类型解析规则更倾向于text
上的运算符。
但所有这些都不允许您创建排除约束,因为您的运算符与运算符类没有关联,这对于确定要使用哪种索引是必要的。
您必须为每个btree
index method strategies创建匹配函数,并使用这些函数为btree
定义运算符类。