簡體   English   中英

帶有比較謂詞的PostgreSQL排除約束

[英]PostgreSQL Exclusion constraint with comparison predicate

有簡單的模仿唯一約束就像

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

但是如何使用IS NOT DISTINCT FROM而不是= (因此表中只有一個NULL值)?

創建函數如f(anyelement, anyelement)和運算符失敗,因為null具有未知類型。 還有一個問題:是否有可能將IS NOT DISTINCT FROM謂詞包裝到PostgreSQL中的運算符中?

請耐心等待,我沒有尋找替代解決方案,我知道它很多:)

另外閱讀: 比較運算符

創建一個與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 索引方法策略創建一個匹配函數,並使用這些函數為btree定義一個運算符類。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM