Gaussdb模式匹配操作符详细介绍

Gaussdb模式匹配操作符详细介绍

gaussdb数据库目前提供了三种独立的实现模式匹配的方法,分别为LIKE操作符、SIMILAR TO操作符和POSIX-风格的正则表达式 。除了这些基本的操作符外,还有一些函数可用于提取或替换匹配子串并在匹配位置分离一个串。

1、like

like应该是我们经常使用的方式,判断字符串是否能匹配上LIKE后的模式字符串,如果匹配,则LIKE表达式返回为真(NOT LIKE表达式返回假),否则返回为假(NOT LIKE表达式返回真)。如果不添加%或_,即全部字符串匹配相当于=;如果要匹配在字符串内的任何位置,该模式必须以%开头和结尾。

规则说明
%任意字符串的通配符
_(匹配)任何单个字符
\\ 、%、\_转义字符,查询的内容中需要匹配%、_、\,需要在前面添加\
like大小写敏感即区分大小写
ilike大小写不敏感即不区分大小写

通配符

openGauss=# SELECT 'abc' LIKE 'abc' AS RESULT;
 result 
--------
 t
(1 row)

openGauss=# SELECT 'abc' LIKE 'a%' AS RESULT;
 result 
--------
 t
(1 row)
openGauss=# SELECT 'abc' LIKE '%b%' AS RESULT;
 result 
--------
 t
(1 row)

openGauss=# SELECT 'abc' LIKE '_b_' AS RESULT;
 result 
--------
 t
(1 row)

openGauss=# SELECT 'abc' LIKE 'c' AS RESULT;
 result 
--------
 f
(1 row)

是否区分大小写

openGauss=# select 'abc' like 'A%' as result;
 result 
--------
 f
(1 row)

openGauss=# select 'abc' ilike 'A%' as result;
 result 
--------
 t
(1 row)

ESCAPE子句指定其他逃逸字符

下面案例中的模式字符串’abc %%',第一个%由于自定义了逃逸字符 ,因此$%作为一个普通字符存在,只需要匹配查询的内容中包含有%;最后一个%则是通配符作用

openGauss=# with tmp as (select 'abc%def' as result union all select 'abcdef' as result)
openGauss-# select * from tmp where result like 'abc$%%'  escape '$';
 result  
---------
 abc%def
(1 row)

2、SIMILAR TO

SIMILAR TO的用法和LIK非常类似,其结果也是根据匹配结果返回真假。另外比较特殊的就是支持使用SQL标准定义的正则表达式理解模式,支持的规则除了%和_之外,也支持下面这些从POSIX正则表达式借用的模式匹配元字符。

元字符含义
|表示选择(两个候选之一)
*表示重复前面的项零次或更多次,可以理解为任意次
+表示重复前面的项一次或更多次
?表示重复前面的项零次或一次
{m}表示重复前面的项刚好m次。
{m,}表示重复前面的项m次或更多次
{m,n}表示重复前面的项至少m次并且不超过n次
()把多个项组合成一个逻辑项,就相当于把整个()内的内容作为匹配项
[…]声明一个字符类,就像POSIX正则表达式一样

针对上述描述重复的次数,是指元字符修饰的字符或者字符组重复多少次,不要理解为该字符或字符组可以和源字符串可以匹配多少次

常见元字符使用

--|元字符
openGauss=# SELECT 'abc' SIMILAR TO '%(af|bc)%' AS RESULT;
 result 
--------
 t
(1 row)
--*元字符
--当前的*时,即使没有可匹配的内容,也返回的是true
openGauss=# SELECT 'abc' SIMILAR TO '%(o)*%' AS RESULT;
 result 
--------
 t
(1 row)

openGauss=# SELECT 'abcdefosp' SIMILAR TO '%(o)*%' AS RESULT;
 result 
--------
 t
(1 row)
--+元字符,该示例由于一次也未匹配到,所以返回false
openGauss=# SELECT 'abc' SIMILAR TO '%(o)+%' AS RESULT;
 result 
--------
 f
(1 row)
--+元字符,该示例匹配到多次o,所以返回true
openGauss=# SELECT 'abcdefooosp' SIMILAR TO '%(o)+%' AS RESULT;
 result 
--------
 t
(1 row)
--?元字符,,该示例未匹配,返回结果也是true
openGauss=# SELECT 'abc' SIMILAR TO '%(o)?%' AS RESULT;
 result 
--------
 t
(1 row)
--{m,n}元字符,对于字符组oo,需要至少匹配2次,即为oooo,可知原字符串不符合结果,返回结果为false。
openGauss=# SELECT 'abcoodefoooosp' SIMILAR TO '%(oo){2,3}%' AS RESULT;
 result 
--------
 f
(1 row)
SELECT 'abcoodefoooosp' SIMILAR TO '%(oo){2,3}%' AS RESULT;

3、POSIX正则表达式

正则表达式是一个字符序列,它是定义一个串集合(一个正则集)的缩写。 如果一个串是正则表达式描述的正则集中的一员时, 我们就说这个串匹配该正则表达式。 POSIX正则表达式提供了比LIKE和SIMILAR TO操作符更强大的含义。列出了所有可用于POSIX正则表达式模式匹配的操作符。

正则表达式匹配操作符

操作符描述例子
~匹配正则表达式,大小写敏感,等价与like‘thomas’ ~ ‘.thomas.
~*匹配正则表达式,大小写不敏感,等价与ilike‘thomas’ ~* ‘.Thomas.
!~不匹配正则表达式,大小写敏感,等价与not like‘thomas’ !~ ‘.Thomas.
!~*不匹配正则表达式,大小写不敏感,等价与not ilike‘thomas’ !~* ‘.vadim.
--匹配正则表达式,大小写敏感
openGauss=# SELECT 'abc' ~ 'Abc' AS RESULT;
 result 
--------
 f
(1 row)

--匹配正则表达式,大小写不敏感
openGauss=# SELECT 'abc' ~* 'Abc' AS RESULT;
 result 
--------
 t
(1 row)

--不匹配正则表达式,大小写敏感
openGauss=# SELECT 'abc' !~ 'Abc' AS RESULT;
 result 
--------
 t
(1 row)
--不匹配正则表达式,大小写不敏感
openGauss=# SELECT 'abc'!~* 'Abc' AS RESULT;
 result 
--------
 f
(1 row)

匹配规则

与LIKE不同,正则表达式允许匹配串里的任何位置,除非该正则表达式显式地挂接在串的开头或者结尾。

除了上文提到的元字符外, POSIX正则表达式还支持下列模式匹配元字符。

元字符含义
\转义字符
^表示串开头的匹配
$表示串末尾的匹配
.匹配任意单个字符
(abc)把多个字符组合成一个匹配原子,就相当于把整个()内的内容作为匹配项
[abc]匹配abc中的任何一个字符,内部可以嵌套(abc),然后这个做一个原子,比如:[abc(de)]
[^abc]负值字符集合。匹配未包含的任意字符。例如,[^abc]可以匹配“plain”中的“plin”任一字符。
|表示选择(两个候选之一)例如: a|b
\d匹配任何数字,就像 [[:digit:]]
\s匹配任何空白字符,就像 [[:space:]] ,包括空格、制表符和换行
\w匹配任何单词字符,就像 [[:word:]]
\D匹配任何非数字,就像 [^[:digit:]]
\S匹配任何非空白字符,就像 [^[:space:]]
\W匹配任何非单词字符,就像 [^[:word:]]
\A只在串开头匹配(与^的不同)
\m只在一个词的开头匹配
\M只在一个词的末尾匹配
\y只在一个词的开头或末尾匹配
\Y只在一个词的不是开头或末尾的点上匹配
\Z只在串的末尾匹配(与$的不同)
\r回车
常见元字符使用
--()匹配规则
openGauss=# select 'abc' ~ '(ab|ac)' as result;
 result 
--------
 t
(1 row)
--[]匹配规则,其中的任何一个字符匹配到源字符串就返回true
openGauss=# select 'abc' ~ '[bef]' as result;
 result 
--------
 t
(1 row)

--[^abc],只要源字符串含有非限定范围的字符,就返回true
openGauss=# select 'china' ~ '[^abc]' as result;
 result 
--------
 t
(1 row)
--匹配空白字符
openGauss=# select 'china ' ~ '\s' as result;
 result 
--------
 t
(1 row)

匹配两个词组查询场景

下面的案例主要就是查询数据库会话中使用is not null或者is null语法的场景

--如果两个词组中间只包含空格,可以直接添加\s,另外还需要考虑有多个空白的时候,因此也需要添加量词来修饰,可以添加+
openGauss=# select 'select * from t1 where is   not null' ~ '(is)\s+(not)' as result;
 result 
--------
 t
(1 row)

--如果两个词组中间包含不固定的字符且至少有一个字符,可以添加 .+来指定任意字符;
openGauss=# select 'select * from t1 where is not null' ~ '(is).*(null)' as result;
 result 
--------
 t
(1 row)
--如果两个词组中间,可能存在not字符串且不存在其他字符串,可以适用((not)?\s+)修饰not字符串的匹配规则,外层的括号可以不需要。
--外层的括号只是为了方便区分匹配的分组
openGauss=# select 'select * from t1 where is  not   null' ~ '(is)\s+((not)?\s+)(null)' as result;
 result 
--------
 t
(1 row)
--去掉括号后的结果和之前是一致的
openGauss=# select 'select * from t1 where is  not   null' ~ '(is)\s+(not)?\s+(null)' as result;
 result 
--------
 t
(1 row)

匹配规则,是否需要考虑换行

匹配多个词组的时候,目前验证,对于空格、制表符、换行,都按照匹配任何空白字符处理即可。

create table t1 (id int,context varchar(1000));

insert into t1 values(1,'select * from t1 
where is   
not null');
insert into t1 values(2,'select * from t1 where is   
 null');
insert into t1 values(3,'select * from t1 where 1=2');
insert into t1 values(4,'not else');
insert into t1 values(5,'ifnot else');
insert into t1 values(6,'notrr else');
insert into t1 values(7,'select * from t1 where is not null');
--查询
openGauss=> select * from t1 where regexp_like(context,'(is)\s+(not)?\s?(null)','i');
 id |              context               
----+------------------------------------
  1 | select * from t1 \r               +
    | where is   \r                     +
    | not null
  2 | select * from t1 where is   \r    +
    |  null
  7 | select * from t1 where is not null
(3 rows)
--插入
insert into t1 values(8,'where group
 by ');
insert into t1 values(9,'where group by ');
--匹配换行\r
openGauss=> select * from t1 where regexp_like(context,'(group)\r+','i');
 id |    context    
----+---------------
  8 | where group\r+
    |  by 
(1 row)
--匹配任何空白字符\s,根据结果可知,\s是包含换行信息的
openGauss=> select * from t1 where regexp_like(context,'(group)\s+','i');
 id |     context     
----+-----------------
  8 | where group\r  +
    |  by 
  9 | where group by 
(2 rows)

按照词组匹配,精确查找

我们在查询匹配关键字的时候,一般需要精确查找匹配,而不需要那些包含有查询关键字的数据行

--通过正则表达式约束\m和\M来限定一个词的开头和结尾匹配
openGauss=> select * from t1 where regexp_like(context,'\mnot\M','i');
 id |              context               
----+------------------------------------
  1 | select * from t1 \r               +
    | where is   \r                     +
    | not null
  4 | not else
  7 | select * from t1 where is not null
(3 rows)
--\m一个词的开头匹配
openGauss=> select * from t1 where regexp_like(context,'\mnot','i');
 id |              context               
----+------------------------------------
  1 | select * from t1 \r               +
    | where is   \r                     +
    | not null
  4 | not else
  6 | notrr else
  7 | select * from t1 where is not null
(4 rows)
--\M一个词的末尾匹配
openGauss=> select * from t1 where regexp_like(context,'not\M','i');
 id |              context               
----+------------------------------------
  1 | select * from t1 \r               +
    | where is   \r                     +
    | not null
  4 | not else
  5 | ifnot else
  7 | select * from t1 where is not null
(4 rows)

?和*量词的区别

在查询匹配场景下,我个人理解应该是一致的,但是对于一些替换场景则是有区别的

--?是匹配0或1次,所以(o)?b匹配的子串为ob,替换为了foearbaz
openGauss=> SELECT regexp_replace('foobarobaz', '(o)?b', 'e');
 regexp_replace 
----------------
 foearobaz
(1 row)
--*是匹配0或更多次,所以(o)?b匹配的子串为oob,替换为了e,结果为fearbaz
openGauss=> SELECT regexp_replace('foobarobaz', '(o)*b', 'e');
 regexp_replace 
----------------
 fearobaz
(1 row)
--对于flat参数,i表示进行大小写无关的匹配,g表示替换每一个匹配的子字符串而不仅仅是第一个
openGauss=> SELECT regexp_replace('foobarobaz', '(o)*b', 'e','g');
 regexp_replace 
----------------
 feareaz
(1 row)

正则表达式支持的函数

对于具体的正则函数的使用,本文不做详细介绍,后续再写文章详细介绍。正则表达式支持的函数如下,

substring(string from pattern)
描述:截取匹配POSIX正则表达式的子字符串。如果没有匹配它返回空值,否则返回文本中匹配模式的那部分。

regexp_count(string text, pattern text [, position int [, flags text]])
描述:获取满足匹配的子串个数

regexp_instr(string text, pattern text [, position int [, occurrence int [, return_opt int [, flags text]]]])
描述:获取满足匹配条件的子串位置(从1开始)。如果没有匹配的子串,则返回0。
regexp_substr(string text, pattern text [, position int [, occurrence int [, flags text]]])
描述:正则表达式的抽取子串函数。与substr功能相似,正则表达式出现多个并列的括号时,也全部处理

regexp_replace(string, pattern, replacement [,flags ])
描述:替换匹配POSIX正则表达式的子字符串。如果没有匹配pattern,那么返回不加修改的string串。如果有匹配,则返回的string串里面的匹配子串将被replacement串替换掉。
replacement串可以包含\n,其中\n是1到9,表明string串里匹配模式里第n个圆括号子表达式的子串应该被插入,并且它可以包含\&表示应该插入匹配整个模式的子串。
可选的flags参数包含零个或多个改变函数行为的单字母标记。flags 支持的选项值及含义描述如表1 flags 支持的选项值所示。返回值类型:varchar

regexp_matches(string text, pattern text [, flags text])
描述:返回string中所有匹配POSIX正则表达式的子字符串。如果pattern不匹配,该函数不返回行。如果模式不包含圆括号子表达式,则每一个被返回的行都是一个单一元素的文本数组,其中包括匹配整个模式的子串。如果模式包含圆括号子表达式,该函数返回一个文本数组,它的第n个元素是匹配模式的第n个圆括号子表达式的子串。
flags参数为可选参数,包含零个或多个改变函数行为的单字母标记。i表示进行大小写无关的匹配,g表示替换每一个匹配的子字符串而不仅仅是第一个。

regexp_split_to_array(string text, pattern text [, flags text ])
描述:用POSIX正则表达式作为分隔符,分隔string。和regexp_split_to_table相同,不过regexp_split_to_array会把它的结果以一个text数组的形式返回。返回值类型:text[]

regexp_split_to_table(string text, pattern text [, flags text])
描述:用POSIX正则表达式作为分隔符,分隔string。如果没有与pattern的匹配,该函数返回string。如果有至少有一个匹配,对每一个匹配它都返回从上一个匹配的末尾(或者串的开头)到这次匹配开头之间的文本。当没有更多匹配时,它返回从上一次匹配的末尾到串末尾之间的文本。
flags参数包含零个或多个改变函数行为的单字母标记。i表示进行大小写无关的匹配。返回值类型:setof text

regexp_like(text,text,text)
描述:正则表达式的模式匹配函数。返回值类型:bool

总结

本文中整理的正则匹配规则为比较常见的规则,相对来说上手还是比较容易的,这些规则对于我们的日常运维开发应该是足够使用的。另外这三种模式匹配,其实使用场景也是稍微有所不同。

1、like常用于简单的模糊匹配查询

2、SIMILAR TO语法可以支持正则模式匹配,适用于大部分场景

3、正则表达式相比SIMILAR TO,支持一些正则函数的使用并且支持一些其他特殊的匹配规则

总之,正则表达式是一种强大的工具,它在文本处理领域具有广泛的应用,并且具有灵活性、通用性和高效性等优点。通过掌握正则表达式,开发或运维人员能够更高效地处理文本数据。

上述的整理,是通过查看gauss的官网文档并结合PG官网资料整理常用的正则表达式。如果个别内容有误,望各位大佬多多指正。

发现的问题

1、Gaussdb文档没有关于正则表达式匹配规则的详细介绍,希望后续可以完善该部分文档

2、POSIX正则表达式支持的函数中描述中缺少了regexp_like,但是在regexp_like函数详细介绍页是有该函数支持正则表达式的描述
模式匹配,其实使用场景也是稍微有所不同。

1、like常用于简单的模糊匹配查询

2、SIMILAR TO语法可以支持正则模式匹配,适用于大部分场景

3、正则表达式相比SIMILAR TO,支持一些正则函数的使用并且支持一些其他特殊的匹配规则

总之,正则表达式是一种强大的工具,它在文本处理领域具有广泛的应用,并且具有灵活性、通用性和高效性等优点。通过掌握正则表达式,开发或运维人员能够更高效地处理文本数据。

上述的整理,是通过查看gauss的官网文档并结合PG官网资料整理常用的正则表达式。如果个别内容有误,望各位大佬多多指正。

发现的问题

1、Gaussdb文档没有关于正则表达式匹配规则的详细介绍,希望后续可以完善该部分文档

2、POSIX正则表达式支持的函数中描述中缺少了regexp_like,但是在regexp_like函数详细介绍页是有该函数支持正则表达式的描述
在这里插入图片描述

  • 50
    点赞
  • 38
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
PostgreSQL的操作符匹配规则是基于操作符名称和输入参数类型进行匹配的。简单来说,当使用操作符时,PostgreSQL会检查操作符名称和输入参数的数据类型是否匹配。如果匹配,则使用操作符执行操作。如果不匹配,则会尝试进行类型转换,以便匹配一个可用的操作符。 具体来说,PostgreSQL根据以下规则进行操作符匹配: 1. 精确匹配:如果存在一个名称、输入参数数量和数据类型都与操作符使用相同的操作符,则使用操作符执行操作。 2. 隐式类型转换:如果没有精确匹配的操作符,则会尝试进行类型转换,以便匹配一个可用的操作符。例如,如果操作符需要接受整数类型的参数,但输入参数是浮点数,则会将浮点数转换为整数类型。 3. 显式类型强制转换:如果没有隐式类型转换的操作符,则可以使用显式类型强制转换。例如,可以使用CAST函数将输入参数转换为所需的数据类型,以便匹配一个可用的操作符。 4. 模糊匹配:如果没有精确匹配、隐式类型转换或显式类型强制转换的操作符,则会尝试进行模糊匹配。在模糊匹配,PostgreSQL会查找与操作符名称相似的操作符,并使用它们执行操作。模糊匹配通常是最不可靠的匹配方法,因为它可能会匹配到错误的操作符。 总之,PostgreSQL的操作符匹配规则是非常灵活的,可以根据不同的输入参数类型和操作符名称,自动匹配可用的操作符

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

墨竹~

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值