是否可以重载 PostgreSQL 中现有的相等运算符,以给出
int
或 real
类型的两个值之间的相等性的新定义?我认为这违反了超载规则,但我想知道是否有办法做到这一点。我试过这个:
CREATE OPERATOR = ( LEFTARG = real ,
RIGHTARG = real,
PROCEDURE = new_equality,
COMMUTATOR = = ,
NEGATOR = !=
);
CREATE OR REPLACE FUNCTION new_equality (real, real) RETURNS BOOLEAN AS
$$
SELECT abs ($1 - $2) < 0,2 ;
$$ LANGUAGE PL/PGSQL
但是当我在查询中使用相等运算符时,我没有得到任何结果。
我还尝试将
new_equality()
函数参数定义为我的属性类型,如下所示:
CREATE OR REPLACE FUNCTION new_equality (Student.age%TYPE, Student.age%TYPE) RETURNS BOOLEAN
AS
$$
SELECT abs ($1 - $2) < 0,2;
$$ lANGUAGE PL/PGSQL
但是我收到一条通知,说 Postgres 将它们转换为
real
,当我在查询中使用相等运算符时,我仍然没有得到任何结果。
Laurenz指出了
search_path
的直接问题。还有更多。
这会起作用:
CREATE OR REPLACE FUNCTION public.new_equality (real, real) -- explicit schema!
RETURNS bool
LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE COST 10
RETURN abs($1 - $2) < 0.2;
CREATE OR REPLACE FUNCTION public.new_inequality (real, real) -- explicit schema!
RETURNS bool
LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE COST 10
RETURN abs($1 - $2) >= 0.2;
CREATE OPERATOR public.= ( -- explicit schema!
LEFTARG = real
, RIGHTARG = real
, FUNCTION = public.new_equality
, COMMUTATOR = OPERATOR(public.=) -- explicit schema!
, NEGATOR = OPERATOR(public.!=) -- must also exist
);
CREATE OPERATOR public.!= (
LEFTARG = real
, RIGHTARG = real
, FUNCTION = public.new_inequality
, COMMUTATOR = OPERATOR(public.!=)
, NEGATOR = OPERATOR(public.=)
);
使用
OPERATOR()
构造来调用它:
SELECT id, real '0.1' OPERATOR(public.=) real '0.2';
SELECT id, real '0.1' OPERATOR(public.!=) real '0.2';
SELECT id, real '0.1' OPERATOR(public.<>) real '0.2';
小提琴 - 有更多示例
“标准 SQL”函数的语法至少需要 Postgres 14。参见:
注意更高的运算符优先级,可能会在普通运算符不会的情况下强制使用括号!
您还必须定义您在声明中提到的
NEGATOR
。使用内置的 !=
会是自相矛盾的废话。创建一个匹配运算符,使用模式限定语法引用它。 说明书:
要在
或其他可选参数中给出模式限定的运算符名称,请使用com_op
语法 [...]OPERATOR()
相关:
请注意,
<>
是!=
的自动别名,<>
是SQL中默认的不等运算符。
不合格的
=
将是标准的相等运算符 (OPERATOR(pg_catalog.=)
),而您不会混淆 search_path
来降级 pg_catalog
- 你不应该这样做!降级 pg_catalog
为各种严重问题打开了大门,因为系统对象现在隐藏在一个或多个其他模式后面。 不要这样做,除非你确切地知道自己在做什么。关于search_path
:
使用关键字
FUNCTION
代替误导性的PROCEDURE
,这对于向后兼容仍然有效。参见:
就像评论中建议的一样,使用与现有符号不同的运算符符号以避免冲突可能会更方便。仍然比默认比较运算符具有标准(=更高)运算符优先级,并且不能轻易更改。
LANGUAGE sql
),但您的运算符不会被使用,因为
pg_catalog
隐式地位于
search_path
上。您可以更改
search_path
将
pg_catalog
放在其他地方:
SET search_path = public, pg_catalog;
或者您可以显式引用运算符:
SELECT 1::real OPERATOR(public.=) 1.1::real;