简体   繁体   English

带有比较谓词的PostgreSQL排除约束

[英]PostgreSQL Exclusion constraint with comparison predicate

There is simple to mimic unique constraint like 有简单的模仿唯一约束就像

create table foo(x int, exclude (x with =));

But how is it possible to use IS NOT DISTINCT FROM instead of = (so there is only one NULL value in the table)? 但是如何使用IS NOT DISTINCT FROM而不是= (因此表中只有一个NULL值)?

Creating function like f(anyelement, anyelement) and operator fails because null have unknown type. 创建函数如f(anyelement, anyelement)和运算符失败,因为null具有未知类型。 So yet another question: is it possible to wrap IS NOT DISTINCT FROM predicate into operator in PostgreSQL? 还有一个问题:是否有可能将IS NOT DISTINCT FROM谓词包装到PostgreSQL中的运算符中?

Be patient, I not searching an alternative solution, I know its a lot :) 请耐心等待,我没有寻找替代解决方案,我知道它很多:)

Furthermore reading: Comparison operators 另外阅读: 比较运算符

It is easy to create a function and an operator that corresponds to NOT DISTINCT TO : 创建一个与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 = "==="
);

This will fail if both arguments are untyped NULLs: 如果两个参数都是无类型的NULL,则会失败:

test=> SELECT NULL === NULL;
ERROR:  could not determine polymorphic type because input has type unknown

One solution is to use overloading and define the same function and operator for every type you need: 一种解决方案是使用重载并为您需要的每种类型定义相同的函数和运算符:

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 = "==="
);

Then the example will work: 然后该示例将起作用:

test=> SELECT NULL === NULL;
 ?column? 
----------
 t
(1 row)

This is because the type resolution rules will prefer the operator on text in that case. 这是因为该类型解析规则会优先操作上text在这种情况下。

But all this will not allow you to create an exclusion constraint, because your operator is not associated with an operator class, which is necessary to determine what kind of index is to be used. 但所有这些都不允许您创建排除约束,因为您的运算符与运算符类没有关联,这对于确定要使用哪种索引是必要的。

You would have to create a matching function for each of the btree index method strategies and define an operator class for btree with these functions. 您必须为每个btree 索引方法策略创建一个匹配函数,并使用这些函数为btree定义一个运算符类。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM