PostgreSQL 9.4-在排除约束中使用自定义运算符
查看后,我创建了以下自定义运算符:PostgreSQL 9.4-在排除约束中使用自定义运算符,postgresql,postgresql-9.4,Postgresql,Postgresql 9.4,查看后,我创建了以下自定义运算符: CREATE OR REPLACE FUNCTION is_not_distinct_from( ANYELEMENT, ANYELEMENT ) RETURNS BOOLEAN AS $$ SELECT $1 IS NOT DISTINCT FROM $2; $$ LANGUAGE sql IMMUTABLE; CREATE OPERATOR =!= ( PROCEDURE = is_not_distinct_from(anye
CREATE OR REPLACE FUNCTION is_not_distinct_from(
ANYELEMENT,
ANYELEMENT
)
RETURNS BOOLEAN AS
$$
SELECT $1 IS NOT DISTINCT FROM $2;
$$
LANGUAGE sql
IMMUTABLE;
CREATE OPERATOR =!= (
PROCEDURE = is_not_distinct_from(anyelement,anyelement),
LEFTARG = anyelement,
RIGHTARG = anyelement,
COMMUTATOR = =!=,
NEGATOR = <!>
);
CREATE OR REPLACE FUNCTION is_distinct_from(
ANYELEMENT,
ANYELEMENT
)
RETURNS BOOLEAN AS
$$
SELECT $1 IS DISTINCT FROM $2;
$$
LANGUAGE sql
IMMUTABLE;
CREATE OPERATOR <!> (
PROCEDURE = is_distinct_from(anyelement,anyelement),
LEFTARG = anyelement,
RIGHTARG = anyelement,
COMMUTATOR = <!>,
NEGATOR = =!=
);
我得到以下错误:
错误:运算符==(anyelement,anyelement)不是
运算符系列“datetime_ops”详细信息:排除运算符必须为
与约束的索引运算符类相关
我已经审阅了文档(和),但我很难理解这些材料
此外,可将其视为本文件的副本;然而,这个问题的一个问题是与其他RDBMS的兼容性这个问题专门针对如何处理上述错误。您选择了一个真正的考验。使用一个唯一的索引,它更简单、更安全、更快
CREATE TABLE foo (
foo_id serial PRIMARY KEY,
foo text NOT NULL,
bar timestamptz,
baz timestamptz
);
CREATE TABLE
CREATE UNIQUE INDEX foo_foo_bar_baz_idx ON foo
(foo, coalesce(bar, 'infinity'), coalesce(baz, 'infinity'));
CREATE INDEX
INSERT INTO foo VALUES
(default, '', null, null),
(default, '', now(), null),
(default, '', null, now());
INSERT 0 3
INSERT INTO foo VALUES
(default, '', null, null);
ERROR: duplicate key value violates unique constraint "foo_foo_bar_baz_idx"
DETAIL: Key (foo, (COALESCE(bar, 'infinity'::timestamp with time zone)), (COALESCE(baz, 'infinity'::timestamp with time zone)))=(, infinity, infinity) already exists.
我试图避免在函数索引中使用
coalesce()
,而是坚持EXCLUDE
约束;然而,你说你的答案更简单、更安全、更快,但其他的就不多了。。。请您解释一下所请求方法的问题好吗?Exclude
创建一个唯一索引。那么,如果使用一条语句可以获得类似的结果,为什么还要定义自己的运算符、运算符类和索引类型呢?我认为没有理由避免合并()
,因为是不同的
实际上可以归结为同一件事。为什么更安全?代码越少,麻烦就越少。@losshorse另外,现有的功能比自定义代码要经过大量测试。我同意你的推理(代码越少,麻烦就越少)@jpmc26也提出了一个令人信服的观点。。。我同意你们两位的观点,coalesce()
可能是更好的选择(在这种情况下);但是,您的回答未能回答所提出的问题。。。如果您可以扩展您的答案,以包括如何将自定义运算符绑定到索引(可能有一个示例),那么我将排除它。对于给定的数据和索引类型,您应该这样做。但是,必须非常小心,除非定义了索引实现中预期的所有运算符和函数,否则不要覆盖现有的默认运算符类。这不是一项琐碎的任务,您应该有非常重要的理由来尝试处理它。没有和,opclass文档是非常无用的。btree_gist
扩展的timestamp
的gist实现是,并且,为了让您了解您要进入的内容。FWIW,排除约束似乎不是必需的;我认为这样的约束(理论上)应该可以通过一个唯一的索引和一个定制的B树类来实现。但是我,它似乎不起作用。我怀疑空值的处理是硬连接到索引方法中的。不确定一个类是否会有任何不同。
CREATE TABLE foo (
foo_id serial PRIMARY KEY,
foo text NOT NULL,
bar timestamptz,
baz timestamptz
);
CREATE TABLE
CREATE UNIQUE INDEX foo_foo_bar_baz_idx ON foo
(foo, coalesce(bar, 'infinity'), coalesce(baz, 'infinity'));
CREATE INDEX
INSERT INTO foo VALUES
(default, '', null, null),
(default, '', now(), null),
(default, '', null, now());
INSERT 0 3
INSERT INTO foo VALUES
(default, '', null, null);
ERROR: duplicate key value violates unique constraint "foo_foo_bar_baz_idx"
DETAIL: Key (foo, (COALESCE(bar, 'infinity'::timestamp with time zone)), (COALESCE(baz, 'infinity'::timestamp with time zone)))=(, infinity, infinity) already exists.