postgreSQL 中的自定义操作符示例详解

 更新时间:2025年12月13日 08:56:00   作者:大卫小东(Sheldon)  
文章介绍了PostgreSQL在操作符定义方面的创新和灵活性,包括如何使用OPERATOR()语法显式调用操作符,以及如何自定义操作符以满足特定需求,文章还讨论了PostgreSQL在自定义操作符方面的优势,如操作符重载、索引绑定和对优化器的影响,感兴趣的朋友跟随小编一起看看吧

postgre是想对标Oracle的。所以在定义操作符上也对标了

操作符

看下面这条语句:

SELECT 3 OPERATOR(pg_catalog.+) 4 sum; -- 1️⃣

这条 SQL 看起来很怪,但它在 PostgreSQL 里是完全合法的,并且会正常返回 7。

实际上,它就是我们熟悉的

SELECT 3 + 4; -- 2️⃣

1️⃣ 那行代码其实就是在玩 PostgreSQL 的一个“冷门但正式支持”的语法:显式使用 OPERATOR() 语法来调用操作符。
2️⃣这条语句执行时,PostgreSQL 内部会把 + 解析成一个真正的操作符对象,它的全名是 pg_catalog.+(在系统目录 pg_operator 里能查到)。而1️⃣就是把平时隐藏的内部机制直接写出来了,只不过是用最“啰嗦、最底层”的方式调用加法操作符,你可以把 OPERATOR(schema.操作符名) 理解成“强制指定用哪个操作符来操作左右两边”。

实际上,1️⃣还能写得更短:

SELECT 3 OPERATOR(+) 4; -- 可以省略 schema,默认 pg_catalog

自定义操作符

PostgreSQL 目前具有主流数据库里最强的自定义操作符:

  • 完全自定义新操作符
  • 重载已有操作符(如重定义 +)
  • 操作符可绑定索引(B-Tree, GiST, GIN…)
  • 操作符可以有 commutator / negator
  • 操作符直接影响优化器、索引选择

在这一方面,连Oracle也难以匹敌。

1. 语法

CREATE OPERATOR operator_name (
{ LEFTARG = left_type -- 左操作数类型(单目操作符可省略)
| RIGHTARG = right_type -- 右操作数类型(单目操作符可省略)
| BOTHARG = both_type } -- 左右类型相同时代替上面两个
[, PROCEDURE = function_name ] -- 必须:真正执行的函数
[, COMMUTATOR = com_op ] -- 可选:交换律操作符(如 + 和 + 本身)
[, NEGATOR = neg_op ] -- 可选:取反操作符(如 = 的取反是 <>)
[, RESTRICT = res_proc ] -- 可选:用于优化器选择性估计
[, JOIN = join_proc ] -- 可选:用于优化器连接估计
[, HASHES ] -- 可选:支持 HASH JOIN 和 hash 聚合
[, MERGES ] -- 可选:支持 MERGE JOIN
);

2. 例子 1:创建 !!(双感叹号)前缀操作符,表示“转成大写”

-- 第1步:先创建一个底层函数
CREATE OR REPLACE FUNCTION immutable_upper(text)
RETURNS text AS $$
SELECT upper($1);
$$ LANGUAGE sql IMMUTABLE STRICT;
-- 第2步:创建前缀操作符(右操作数,没有左操作数)
CREATE OPERATOR !! (
RIGHTARG = text, -- 只有右操作数,在右边 → 前缀操作符
PROCEDURE = immutable_upper -- 调用上面那个函数
);
-- 第3步:试用
SELECT !! 'hello'; -- 返回 HELLO
SELECT !! column_name FROM users;

不知道你有没有疑惑:这不还是用PG定义的函数吗?不还是PG本来就支持的东西吗?
没错。操作符只是一种“糖”,让你更方便、简洁的使用本来就有的能力。

3. 例子 2:创建自定义的 === 操作符,表示“可空相等”(带索引支持)

先创建函数

CREATE OR REPLACE FUNCTION geometry_strict_equal(anyelement, anyelement)
RETURNS boolean AS $$
SELECT $1 IS NOT DISTINCT FROM $2;
$$ LANGUAGE sql IMMUTABLE;

IS NOT DISTINCT FROM 是什么?这是 PostgreSQL 特有的“空值安全的相等比较”

  • 当 a = b → true
  • 当 a 和 b 都是 NULL → true (普通的=,NULL = NULL → null (不为 true))
  • 其他情况 → false
  • 普通的=,NULL = NULL时 → null (不为 true)。

mysql中这个操作叫<=>“太空船运算符”,但是PG已经存在这个操作符了,主要在pg_trgm扩展中计算相似度,所以这里我们定义成===

IMMUTABLE 表示同样输入,永远返回同样的输出;可以用于索引;可以内联与优化。

anyelement 表示任意类型的参数,但是两个参数类型要一样。

接下来创建操作符

CREATE OPERATOR === (
LEFTARG = anyelement,
RIGHTARG = anyelement,
PROCEDURE = geometry_strict_equal,
COMMUTATOR = ===, -- 自己和自己交换律
NEGATOR = !==, -- 稍后会创建它的取反
HASHES, -- 支持 hash join / hash agg
MERGES -- 支持 merge join
);
-- 创建取反操作符 !==
CREATE OPERATOR !== (
LEFTARG = anyelement,
RIGHTARG = anyelement,
PROCEDURE = geometry_strict_equal,
NEGATOR = === -- 互相指向对方
);

看一下例子:

比较的两个对象必须是同类型的,不然会报错,所以要明确指出null是什么类型。
如果是用在表查询语句中,因为表结构和字段类型是确定的,所以不用指出来。

4. 查询操作符

SELECT
n.nspname AS schema,
o.oprname AS operator, -- 操作符名称
format_type(o.oprleft, NULL) AS left_type,
format_type(o.oprright, NULL) AS right_type,
p.proname AS function_name -- 函数名称
FROM pg_operator o
JOIN pg_namespace n ON n.oid = o.oprnamespace
JOIN pg_proc p ON p.oid = o.oprcode
WHERE n.nspname NOT IN ('pg_catalog')
and o.oprname = '!!'; -- 可以去掉过滤看看

5. 删除操作符

DROP OPERATOR IF EXISTS !! (NONE, text); -- 先删除操作符,必须传左右两个参数,没有的写NONE
DROP FUNCTION public.immutable_upper(text); -- 函数如果还要用可以不删

小练习

给 ilike 写一个操作符。我定义好函数了:

CREATE OR REPLACE FUNCTION chinese_ilike(text, text)
RETURNS boolean AS $$
SELECT $1 ILIKE $2;
$$ LANGUAGE sql IMMUTABLE STRICT;

到此这篇关于postgreSQL 中的自定义操作符示例详解的文章就介绍到这了,更多相关postgreSQL自定义操作符内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 如何查看postgres数据库端口

    如何查看postgres数据库端口

    这篇文章主要介绍了如何查看postgres数据库端口操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2021-01-01
  • 15个postgresql数据库实用命令分享

    15个postgresql数据库实用命令分享

    这篇文章主要介绍了15个实用的postgresql数据库命令分享,都是一些技巧性的postgresql命令,需要的朋友可以参考下
    2014-07-07
  • 使用PostGIS完成两点间的河流轨迹及流经长度的计算(推荐)

    使用PostGIS完成两点间的河流轨迹及流经长度的计算(推荐)

    这篇文章主要介绍了使用PostGIS完成两点间的河流轨迹及流经长度的计算,使用POSTGIS及其扩展pgrouting计算给定两点间的河流流经区域和河流长度,需要的朋友可以参考下
    2022-01-01
  • PostgreSQL实现跨数据库授权查询的详细步骤

    PostgreSQL实现跨数据库授权查询的详细步骤

    在PostgreSQL中,由于一个数据库实例下的不同数据库在逻辑上是隔离的,你不能像在同一个数据库内跨模式那样直接查询,因此,你需要分两步走:先授权,后查询,所以本文给大家介绍了PostgreSQL实现跨数据库授权查询的详细步骤,需要的朋友可以参考下
    2025-10-10
  • 详解如何在Ubuntu 18.04上安装和使用PostgreSQL

    详解如何在Ubuntu 18.04上安装和使用PostgreSQL

    关系数据库管理系统是许多网站和应用程序的关键组件,它们提供了一种结构化的方式来存储、组织和访问信息,本文演示了如何在 Ubuntu 18.04 VPS 实例上安装 Postgres,并提供了基本数据库管理的说明,需要的朋友可以参考下
    2024-07-07
  • 修改postgresql存储目录的操作方式

    修改postgresql存储目录的操作方式

    这篇文章主要介绍了修改postgresql存储目录的操作方式,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2021-01-01
  • Linux CentOS 7安装PostgreSQL9.3图文教程

    Linux CentOS 7安装PostgreSQL9.3图文教程

    这篇文章主要为大家详细介绍了Linux CentOS 7安装PostgresSQL9.3图文教程,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2016-11-11
  • 使用PostgreSQL的JSONB数据类型进行高效查询的示例代码

    使用PostgreSQL的JSONB数据类型进行高效查询的示例代码

    PostgreSQL的JSONB数据类型提供了一种灵活的方式来存储和查询JSON格式的数据,下面我们将详细讨论如何使用JSONB数据类型进行高效查询,并提供相应的解决方案和示例代码,需要的朋友可以参考下
    2024-04-04
  • PostgreSQL创建触发器的实现示例

    PostgreSQL创建触发器的实现示例

    PostgreSQL的触发器Trigger是一类特殊的数据库对象,本文主要介绍了PostgreSQL创建触发器的实现示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2025-06-06
  • PostgreSQL 序列(Sequence) 与 Oracle 序列对比差异分析

    PostgreSQL 序列(Sequence) 与 Oracle 序列对比差异分

    PostgreSQL 和 Oracle 都提供了序列(Sequence)功能,但在实现细节和使用方式上存在一些重要差异,下面给大家介绍PostgreSQL 序列(Sequence) 与 Oracle 序列对比差异分析,感兴趣的朋友一起看看吧
    2025-05-05

最新评论