MySQL:如何通过子查询的动态正则值列表实现正则匹配?
解决动态正则匹配的问题
你的问题出在REGEXP IN (...)的语法上——MySQL的REGEXP操作符只接受单个正则表达式字符串作为参数,而IN是用来判断值是否在集合中的逻辑,两者不能这么混用。要实现从tableB动态获取正则项的需求,我们需要先把tableB里的所有关键词拼接成一个用|分隔的正则表达式,再用这个拼接后的字符串去匹配tableA的内容。
基础解决方案
直接用GROUP_CONCAT把tableB中的words字段拼接成一个符合要求的正则串:
SELECT IF(tableA.text REGEXP (SELECT GROUP_CONCAT(words SEPARATOR '|') FROM tableB), 'YES', 'NO') AS `BLACK_LIST`, tableA.text, tableA.ID FROM tableA;
这个语句的逻辑是:
- 子查询
SELECT GROUP_CONCAT(words SEPARATOR '|') FROM tableB会把tableB里的所有关键词合并成类似textA|textB|blablabla的字符串,和你原来硬编码的正则格式完全一致。 - 然后用这个动态生成的正则串去匹配tableA的
text字段,匹配成功返回YES,否则返回NO。
处理边界情况
如果tableB是空表,GROUP_CONCAT会返回NULL,这时候REGEXP NULL的结果也是NULL,IF会默认返回NO。如果你想让逻辑更严谨,可以用COALESCE把NULL替换成一个永远不匹配的正则(比如^$,仅匹配空字符串):
SELECT IF(tableA.text REGEXP COALESCE((SELECT GROUP_CONCAT(words SEPARATOR '|') FROM tableB), '^$'), 'YES', 'NO') AS `BLACK_LIST`, tableA.text, tableA.ID FROM tableA;
处理正则特殊字符
如果tableB中的words包含正则特殊字符(比如.、*、+等),而你只是想匹配这些字符的字面意思,需要先对特殊字符进行转义。可以用REGEXP_REPLACE来处理:
SELECT IF(tableA.text REGEXP COALESCE(( SELECT GROUP_CONCAT( REGEXP_REPLACE(words, '([.\\\\+*?\\[\\]^$(){}=!<>|:-])', '\\\\$1') SEPARATOR '|' ) FROM tableB ), '^$'), 'YES', 'NO') AS `BLACK_LIST`, tableA.text, tableA.ID FROM tableA;
这个转义逻辑会把每个正则特殊字符前面加上反斜杠,确保它们被当作普通字符匹配,不会触发正则的特殊语法。
内容的提问来源于stack exchange,提问作者SimonFreeman
相关产品推荐
相关产品推荐

