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

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

比較的兩個對象必須是同類型的,不然會報(bào)錯,所以要明確指出null是什么類型。
如果是用在表查詢語句中,因?yàn)楸斫Y(jié)構(gòu)和字段類型是確定的,所以不用指出來。
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 = '!!'; -- 可以去掉過濾看看5. 刪除操作符
DROP OPERATOR IF EXISTS !! (NONE, text); -- 先刪除操作符,必須傳左右兩個參數(shù),沒有的寫NONE DROP FUNCTION public.immutable_upper(text); -- 函數(shù)如果還要用可以不刪
小練習(xí)
給 ilike 寫一個操作符。我定義好函數(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)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Postgresql排序與limit組合場景性能極限優(yōu)化詳解
這篇文章主要介紹了Postgresql排序與limit組合場景性能極限優(yōu)化詳解,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-12-12
postgresql 實(shí)現(xiàn)多表關(guān)聯(lián)刪除
這篇文章主要介紹了postgresql 實(shí)現(xiàn)多表關(guān)聯(lián)刪除操作,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧2021-01-01
詳解PostgreSQL提升批量數(shù)據(jù)導(dǎo)入性能的n種方法
這篇文章主要介紹了PostgreSQL提升批量數(shù)據(jù)導(dǎo)入性能的n種方法,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-03-03
PostgreSQL中關(guān)閉死鎖進(jìn)程的方法
這篇文章主要介紹了PostgreSQL中關(guān)閉死鎖進(jìn)程的方法,本文給出兩種解決這問題的方法,需要的朋友可以參考下2015-02-02
postgresql 賦權(quán)語句 grant的正確使用說明
這篇文章主要介紹了postgresql 賦權(quán)語句 grant的正確使用說明,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧2021-01-01
postgresql實(shí)現(xiàn)對已有數(shù)據(jù)表分區(qū)處理的操作詳解
這篇文章主要為大家詳細(xì)介紹了postgresql實(shí)現(xiàn)對已有數(shù)據(jù)表分區(qū)處理的操作的相關(guān)知識,文中的示例代碼講解詳細(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查詢自動將大寫的名稱轉(zhuǎn)換為小寫的案例
這篇文章主要介紹了postgresql查詢自動將大寫的名稱轉(zhuǎn)換為小寫的案例,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧2021-01-01

