功能概述
PostgreSQL 内置的 POSIX 正则实现基于 NFA/ 回溯,遇到复杂模式或长字符串时容易触发指数级回溯(catastrophic backtracking),成为 CPU 热点。tencentdb_regex 扩展将 Google RE2 引擎(deterministic 自动机、有界最坏复杂度)打包进云数据库 PostgreSQL,提供与主干 regexp_* 语义对齐但性能更稳定的替代函数。
前置条件
PostgreSQL 18,版本 ≥ v18.4_r1.10。
使用限制
正则语法遵循 RE2 语法(PCRE 兼容子集,不支持反向引用 \\1 与部分 look-around)。若正则中依赖这些高级特性,请继续使用主干 regexp_*。
tencentdb_regex 的 flags 语义与主干 regexp_* 一致(g、i、m、s、x 等),但底层交给 RE2,实现细节可能微小差异。
schema 为 tencentdb,建议将 tencentdb 加入 search_path 或显式写 tencentdb.regexp_xxx。
创建插件
CREATE EXTENSION tencentdb_regex;-- 可选:加入搜索路径以便直接写 regexp_replace(...)SET search_path = tencentdb, public;SELECT extname, extversion FROM pg_extension WHERE extname = 'tencentdb_regex';
函数清单
以下函数均有 tencentdb.regexp_* 与 tencentdb_regexp_* 两种命名。
regexp_replace
tencentdb.regexp_replace(source text, pattern text, replacement text)RETURNS text;tencentdb.regexp_replace(source text, pattern text, replacement text, flags text)RETURNS text;
作用等价于主干 regexp_replace。flags 常用值:
g:全局替换(默认仅第一处)。
i:忽略大小写。
m:多行模式(^/$ 匹配行首/行尾)。
regexp_match / regexp_matches
tencentdb.regexp_match(source text, pattern text) RETURNS text[];tencentdb.regexp_match(source text, pattern text, flags text) RETURNS text[];tencentdb.regexp_matches(source text, pattern text) RETURNS SETOF text[];tencentdb.regexp_matches(source text, pattern text, flags text) RETURNS SETOF text[];
regexp_match 返回首个匹配的捕获组数组;regexp_matches 是 SRF,返回所有匹配(配合 g flag)。
regexp_split_to_array / regexp_split_to_table
tencentdb.regexp_split_to_array(source text, pattern text) RETURNS text[];tencentdb.regexp_split_to_array(source text, pattern text, flags text) RETURNS text[];tencentdb.regexp_split_to_table(source text, pattern text) RETURNS SETOF text;tencentdb.regexp_split_to_table(source text, pattern text, flags text) RETURNS SETOF text;
按 pattern 分割字符串。前者返回数组,后者以 SRF 返回每段。
regexp_extract
tencentdb.regexp_extract(source text, pattern text, group_id integer) RETURNS text;tencentdb.regexp_extract(source text, pattern text, group_id integer, flags text) RETURNS text;
返回首次匹配中第 group_id 个捕获组(0表示整段匹配)。无匹配或该组未参与匹配时返回 NULL。
regexp_count
tencentdb.regexp_count(source text, pattern text) RETURNS integer;tencentdb.regexp_count(source text, pattern text, flags text) RETURNS integer;
返回 pattern 在 source 中的匹配次数。
regexp_like
tencentdb.regexp_like(source text, pattern text) RETURNS boolean;tencentdb.regexp_like(source text, pattern text, flags text) RETURNS boolean;
判定是否存在至少一次匹配。等价于 source ~ pattern / source ~* pattern,但走 RE2。
使用示例
CREATE EXTENSION IF NOT EXISTS tencentdb_regex;SET search_path = tencentdb, public;-- 1) 全局替换(RE2 版),大小写不敏感SELECT regexp_replace('Hello World, hello RE2', 'hello', 'hi', 'gi');-- 2) 抽取所有 URL 主机部分SELECT regexp_matches('see http://a.com and https://b.io/xyz','(?i)https?://([^/\\s]+)', 'g');-- 3) 分割为表SELECT regexp_split_to_table('a1b22c333d', '[0-9]+') AS part;-- 4) 抽取第 N 个分组SET search_path = tencentdb, public;SELECT regexp_extract('user_id=42; name=alice','user_id=([0-9]+); name=([a-z]+)', 2);-- alice-- 5) 计数SELECT regexp_count('aaa bbb aa cc aaaa', 'a+');-- 6) 存在性SELECT regexp_like('info@tencent.com', '^[\\w.+-]+@[\\w-]+\\.[\\w.-]+$');
与主干函数并存:由于均在 tencentdb schema 下,业务可以按需选择,例如:
-- 明确走 RE2SELECT tencentdb.regexp_replace(col, pat, rep, 'g') FROM tbl;-- 依然使用主干SELECT pg_catalog.regexp_replace(col, pat, rep, 'g') FROM tbl;