postgreSQL?中的自定義操作符示例詳解
postgre是想對(duì)標(biāo)Oracle的。所以在定義操作符上也對(duì)標(biāo)了
操作符
看下面這條語(yǔ)句:
SELECT 3 OPERATOR(pg_catalog.+) 4 sum; -- 1??
這條 SQL 看起來(lái)很怪,但它在 PostgreSQL 里是完全合法的,并且會(huì)正常返回 7。
實(shí)際上,它就是我們熟悉的
SELECT 3 + 4; -- 2??
1?? 那行代碼其實(shí)就是在玩 PostgreSQL 的一個(gè)“冷門但正式支持”的語(yǔ)法:顯式使用 OPERATOR() 語(yǔ)法來(lái)調(diào)用操作符。
2??這條語(yǔ)句執(zhí)行時(shí),PostgreSQL 內(nèi)部會(huì)把 + 解析成一個(gè)真正的操作符對(duì)象,它的全名是 pg_catalog.+(在系統(tǒng)目錄 pg_operator 里能查到)。而1??就是把平時(shí)隱藏的內(nèi)部機(jī)制直接寫(xiě)出來(lái)了,只不過(guò)是用最“啰嗦、最底層”的方式調(diào)用加法操作符,你可以把 OPERATOR(schema.操作符名) 理解成“強(qiáng)制指定用哪個(gè)操作符來(lái)操作左右兩邊”。
實(shí)際上,1??還能寫(xiě)得更短:
SELECT 3 OPERATOR(+) 4; -- 可以省略 schema,默認(rèn) pg_catalog
自定義操作符
PostgreSQL 目前具有主流數(shù)據(jù)庫(kù)里最強(qiáng)的自定義操作符:
- 完全自定義新操作符
- 重載已有操作符(如重定義 +)
- 操作符可綁定索引(B-Tree, GiST, GIN…)
- 操作符可以有 commutator / negator
- 操作符直接影響優(yōu)化器、索引選擇
在這一方面,連Oracle也難以匹敵。
1. 語(yǔ)法
CREATE OPERATOR operator_name (
{ LEFTARG = left_type -- 左操作數(shù)類型(單目操作符可省略)
| RIGHTARG = right_type -- 右操作數(shù)類型(單目操作符可省略)
| BOTHARG = both_type } -- 左右類型相同時(shí)代替上面兩個(gè)
[, PROCEDURE = function_name ] -- 必須:真正執(zhí)行的函數(shù)
[, COMMUTATOR = com_op ] -- 可選:交換律操作符(如 + 和 + 本身)
[, NEGATOR = neg_op ] -- 可選:取反操作符(如 = 的取反是 <>)
[, RESTRICT = res_proc ] -- 可選:用于優(yōu)化器選擇性估計(jì)
[, JOIN = join_proc ] -- 可選:用于優(yōu)化器連接估計(jì)
[, HASHES ] -- 可選:支持 HASH JOIN 和 hash 聚合
[, MERGES ] -- 可選:支持 MERGE JOIN
);2. 例子 1:創(chuàng)建 !!(雙感嘆號(hào))前綴操作符,表示“轉(zhuǎn)成大寫(xiě)”
-- 第1步:先創(chuàng)建一個(gè)底層函數(shù) CREATE OR REPLACE FUNCTION immutable_upper(text) RETURNS text AS $$ SELECT upper($1); $$ LANGUAGE sql IMMUTABLE STRICT; -- 第2步:創(chuàng)建前綴操作符(右操作數(shù),沒(méi)有左操作數(shù)) CREATE OPERATOR !! ( RIGHTARG = text, -- 只有右操作數(shù),在右邊 → 前綴操作符 PROCEDURE = immutable_upper -- 調(diào)用上面那個(gè)函數(shù) ); -- 第3步:試用 SELECT !! 'hello'; -- 返回 HELLO SELECT !! column_name FROM users;

不知道你有沒(méi)有疑惑:這不還是用PG定義的函數(shù)嗎?不還是PG本來(lái)就支持的東西嗎?
沒(méi)錯(cuò)。操作符只是一種“糖”,讓你更方便、簡(jiǎn)潔的使用本來(lái)就有的能力。
3. 例子 2:創(chuàng)建自定義的 === 操作符,表示“可空相等”(帶索引支持)
先創(chuàng)建函數(shù)
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 特有的“空值安全的相等比較”
- 當(dāng) a = b → true
- 當(dāng) a 和 b 都是 NULL → true (普通的=,NULL = NULL → null (不為 true))
- 其他情況 → false
- 普通的=,NULL = NULL時(shí) → null (不為 true)。
mysql中這個(gè)操作叫<=>“太空船運(yùn)算符”,但是PG已經(jīng)存在這個(gè)操作符了,主要在pg_trgm擴(kuò)展中計(jì)算相似度,所以這里我們定義成===。
IMMUTABLE 表示同樣輸入,永遠(yuǎn)返回同樣的輸出;可以用于索引;可以內(nèi)聯(lián)與優(yōu)化。
anyelement 表示任意類型的參數(shù),但是兩個(gè)參數(shù)類型要一樣。
接下來(lái)創(chuàng)建操作符
CREATE OPERATOR === ( LEFTARG = anyelement, RIGHTARG = anyelement, PROCEDURE = geometry_strict_equal, COMMUTATOR = ===, -- 自己和自己交換律 NEGATOR = !==, -- 稍后會(huì)創(chuàng)建它的取反 HASHES, -- 支持 hash join / hash agg MERGES -- 支持 merge join ); -- 創(chuàng)建取反操作符 !== CREATE OPERATOR !== ( LEFTARG = anyelement, RIGHTARG = anyelement, PROCEDURE = geometry_strict_equal, NEGATOR = === -- 互相指向?qū)Ψ? );
看一下例子:

比較的兩個(gè)對(duì)象必須是同類型的,不然會(huì)報(bào)錯(cuò),所以要明確指出null是什么類型。
如果是用在表查詢語(yǔ)句中,因?yàn)楸斫Y(jié)構(gòu)和字段類型是確定的,所以不用指出來(lái)。
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 -- 函數(shù)名稱
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 = '!!'; -- 可以去掉過(guò)濾看看5. 刪除操作符
DROP OPERATOR IF EXISTS !! (NONE, text); -- 先刪除操作符,必須傳左右兩個(gè)參數(shù),沒(méi)有的寫(xiě)NONE DROP FUNCTION public.immutable_upper(text); -- 函數(shù)如果還要用可以不刪
小練習(xí)
給 ilike 寫(xiě)一個(gè)操作符。我定義好函數(shù)了:
CREATE OR REPLACE FUNCTION chinese_ilike(text, text) RETURNS boolean AS $$ SELECT $1 ILIKE $2; $$ LANGUAGE sql IMMUTABLE STRICT;
到此這篇關(guān)于postgreSQL 中的自定義操作符示例詳解的文章就介紹到這了,更多相關(guān)postgreSQL自定義操作符內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- postgreSQL?中的自定義操作符示例詳解
- Postgresql在mybatis中報(bào)錯(cuò):操作符不存在:character varying == unknown的問(wèn)題
- Postgresql中LIKE和ILIKE操作符的用法詳解
- PostgreSQL報(bào)錯(cuò) 解決操作符不存在的問(wèn)題
- PostgreSQL基礎(chǔ)知識(shí)之SQL操作符實(shí)踐指南
- PostgreSQL教程(七):函數(shù)和操作符詳解(3)
- PostgreSQL教程(六):函數(shù)和操作符詳解(2)
- PostgreSQL教程(五):函數(shù)和操作符詳解(1)
相關(guān)文章
Postgresql排序與limit組合場(chǎng)景性能極限優(yōu)化詳解
這篇文章主要介紹了Postgresql排序與limit組合場(chǎng)景性能極限優(yōu)化詳解,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-12-12
postgresql 實(shí)現(xiàn)多表關(guān)聯(lián)刪除
這篇文章主要介紹了postgresql 實(shí)現(xiàn)多表關(guān)聯(lián)刪除操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2021-01-01
詳解PostgreSQL提升批量數(shù)據(jù)導(dǎo)入性能的n種方法
這篇文章主要介紹了PostgreSQL提升批量數(shù)據(jù)導(dǎo)入性能的n種方法,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-03-03
PostgreSQL中關(guān)閉死鎖進(jìn)程的方法
這篇文章主要介紹了PostgreSQL中關(guān)閉死鎖進(jìn)程的方法,本文給出兩種解決這問(wèn)題的方法,需要的朋友可以參考下2015-02-02
postgresql 賦權(quán)語(yǔ)句 grant的正確使用說(shuō)明
這篇文章主要介紹了postgresql 賦權(quán)語(yǔ)句 grant的正確使用說(shuō)明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2021-01-01
postgresql實(shí)現(xiàn)對(duì)已有數(shù)據(jù)表分區(qū)處理的操作詳解
這篇文章主要為大家詳細(xì)介紹了postgresql實(shí)現(xiàn)對(duì)已有數(shù)據(jù)表分區(qū)處理的操作的相關(guān)知識(shí),文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2023-12-12
PostgreSQL教程(一):數(shù)據(jù)表詳解
這篇文章主要介紹了PostgreSQL教程(一):數(shù)據(jù)表詳解表的定義、系統(tǒng)字段、表的修改、表的權(quán)限等4大部份內(nèi)容,內(nèi)容種包括表的創(chuàng)建、刪除、修改、字段的修改、刪除、主鍵和外鍵、約束添加修改刪除等,本文講解了,需要的朋友可以參考下2015-05-05
PostgreSQL向量庫(kù)pgvector的使用示例
本文主要介紹了PostgreSQL向量庫(kù)pgvector的使用示例,pgvector是PostgreSQL的向量擴(kuò)展,支持高達(dá)16000維向量存儲(chǔ)及HNSW、IVFFlat索引,下面就來(lái)具體介紹一下2025-08-08
postgresql查詢自動(dòng)將大寫(xiě)的名稱轉(zhuǎn)換為小寫(xiě)的案例
這篇文章主要介紹了postgresql查詢自動(dòng)將大寫(xiě)的名稱轉(zhuǎn)換為小寫(xiě)的案例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2021-01-01

