MySQL中使用REGEXP查询customer表custom_id字段的匹配问题
解决JSON字段的正则匹配问题
嘿,我来帮你搞定这个查询问题~首先得说,你之前的正则写法有问题,因为方括号[]在正则表达式里是特殊字符(用来定义字符集合),直接写的话会被正则引擎解析成别的意思,而不是你想要的JSON里的方括号,所以必须转义才行。另外,针对动态条件的需求,我们可以构造一个灵活的正则表达式来实现。
用REGEXP实现的解决方案
首先,我们需要构造一个能匹配以下逻辑的正则:
- 找到
"20"这个键 - 匹配该键对应的数组(转义方括号)
- 数组中包含
82、83、84中的任意一个(注意这些值有的带引号,有的不带,要兼容两种情况)
对应的SQL语句如下:
SELECT * FROM `customer` WHERE `custom_id` REGEXP '"20":\\[(?:.*?)(\"?82\"?|\"?83\"?|\"?84\"?)(?:.*?)\\]';
正则部分的细节解释:
\"20\"::精确匹配键"20"和后面的冒号\\[:转义方括号,匹配JSON数组的左括号(因为MySQL里正则转义需要双反斜杠)(?:.*?):非贪婪匹配任意字符(非捕获组,避免额外捕获内容),用来跳过数组开头到目标值之间的内容(\"?82\"?|\"?83\"?|\"?84\"?):匹配任意一个目标值,\"?表示引号是可选的(兼容JSON里的字符串和数字类型值),|表示“或”的逻辑(?:.*?)\\]:继续非贪婪匹配到数组的右括号\\](同样需要转义)
动态条件的处理
如果82、83、84是动态变化的,你可以在应用层(比如PHP、Python等)把这些值拼接成正则的分支部分。举个例子,假设你有一个值列表$targetValues = [82,83,84],可以生成这样的片段:
\"?".implode("\"?|\"?", $targetValues)."\"?
然后把这个片段插入到上面的正则中,就能动态生成符合条件的正则表达式了。
更可靠的替代方案:用MySQL JSON函数
其实如果你的MySQL版本是5.7及以上,更推荐用专门的JSON函数来处理,比正则表达式更准确,不容易出现误匹配的情况。比如用JSON_CONTAINS_PATH判断键是否存在,用JSON_CONTAINS判断数组是否包含目标值:
SELECT * FROM `customer` -- 先判断"20"这个键是否存在 WHERE JSON_CONTAINS_PATH(`custom_id`, 'one', '$.20') AND ( -- 匹配带引号的字符串值"82" JSON_CONTAINS(JSON_EXTRACT(`custom_id`, '$.20'), '"82"') OR JSON_CONTAINS(JSON_EXTRACT(`custom_id`, '$.20'), '"83"') -- 匹配不带引号的数字值84 OR JSON_CONTAINS(JSON_EXTRACT(`custom_id`, '$.20'), '84') );
这个方法的优势是直接针对JSON结构解析,不会像正则那样可能匹配到其他无关的内容(比如其他键里的相似数值),稳定性更高。
内容的提问来源于stack exchange,提问作者sakirow
相关产品推荐
相关产品推荐

