MySQL REGEXP 利用正则表达式,在查询中过滤多个字符串
使用MySQL REGEXP正则表达式过滤包含多个字符串的列。解决低版本的MySQL一些正则表达式都不起作用,会报错的问题:1139 - Got error ‘repetition-operator operand invalid’ from regexp
1. 需求说明
由于业务更新,需要在原有的SQL分页查询基础上,添加一个条件,将一个字段带含有(“A”,“B”)字符串的的数据排除在外,排除字符串是根据不同的业务配置的,它是一个动态的参数。
若字段内容为:
- ABCD
- A
- BAA
- AAABBAA
排除内容为:BB,BC,D
则筛选后的结果为:A,BAA
测试数据(要求:过滤带有指定关键字的列):
INSERT INTO `content_xx` (`id`, `content`) VALUES (1, '沿西巴霞曲河谷,穿越“山南之南”');
INSERT INTO `content_xx` (`id`, `content`) VALUES (2, '甘肃西北的干旱戈壁是珍稀植物隐居的乐土');
INSERT INTO `content_xx` (`id`, `content`) VALUES (3, '安集海大峡谷之冬');
INSERT INTO `content_xx` (`id`, `content`) VALUES (4, '喀斯特瀑布 繁星般点缀了 219国道滇桂段');
INSERT INTO `content_xx` (`id`, `content`) VALUES (5, '海蚀拱 中国海岸的珍稀景观');
INSERT INTO `content_xx` (`id`, `content`) VALUES (6, '柴达木水上雅丹 “西部千岛湖”的变化、秘密与隐忧');
INSERT INTO `content_xx` (`id`, `content`) VALUES (7, '伟大的征途——布伦托海大迁徙');
2. 尝试
尝试过的方法:
-
对于这种排除多个字符串的查询,无法用到常规的函数,例如LIKE、UNION、FIND_IN_SET、NOT IN等。
NOT LIKE只能判断单个字符串,NOT IN、FIND_IN_SET又只能精准匹配,无法从语句中提取关键字。
-
通过子查询一遍遍过滤。
然后想到的是既然NOT LIKE可以排除一个,那我就一个个排除不就好了?通过NOT LIKE + EXISTS子查询语句的方式来排除每一个排除项。这种方法比较傻瓜式,且效率肉眼可见的低下,不适合作为首选方法。
- 考虑过在代码中通过正则查询,但是这种方法得自己做物理分页,而且得大幅度修改源代码,效率更低。
3. REGEXP 正则过滤
注意!!!
低版本的MySQL一些正则表达式都不起作用,会报错:1139 - Got error ‘repetition-operator operand invalid’ from regexp
可以参考这篇文章:1139 - Got error ‘repetition-operator operand invalid’ from regexp
我本地的MySQL(8.0)可以执行下面所有的正则,然后放到开发环境(5.7)就只有第三条可以正常使用(这一条还是我不断试出来的)。
select version() from dual;
将正则表达式作为参数拼接进去,就可以形成动态的过滤参数。
搜索的时候大概找到几种可用的方法,参考如下:
- ^((?:河|海岸|峡谷).)*$
SELECT *
FROM content_xx
WHERE content NOT REGEXP "(?:河|海岸|峡谷)"
- ^((?!河|海岸|峡谷).)*$
SELECT *
FROM content_xx
WHERE content REGEXP "^((?!河|海岸|峡谷).)*$"
- ^(.*(河|海岸|峡谷).*)$
SELECT *
FROM content_xx
WHERE content NOT REGEXP "^(.*(河|海岸|峡谷).*)$"
结果:
2 甘肃西北的干旱戈壁是珍稀植物隐居的乐土
4 喀斯特瀑布 繁星般点缀了 219国道滇桂段
6 柴达木水上雅丹 “西部千岛湖”的变化、秘密与隐忧
7 伟大的征途——布伦托海大迁徙
更多推荐
所有评论(0)