【问题标题】:Complex regex in mysql jsonmysql json中的复杂正则表达式
【发布时间】:2019-06-10 09:59:25
【问题描述】:

我在 mysql 表列中有某种缓存列。让我们称之为cacheCol 它的结构为json。

cacheCol 示例

{
    "23": {
        "variationOption": "23",
        "productCode": "322992-015",
        "price": "150",
        "qnt": ""
    },
    "25": {
        "variationOption": "25",
        "productCode": "322992-015",
        "price": "150",
        "qnt": "0"
    },
    "26": {
        "variationOption": "26",
        "productCode": "322992-015",
        "price": "150",
        "qnt": "7"
    }
}

如果特定的 json 部分 qnt > 0,我想选择 myslq 行。在此示例中,键为 26 的部分只有一个匹配。

我已经制定了正则表达式来检查这些值: https://www.regextester.com/?fam=109762

但是当我运行我的查询时

SELECT * FROM "tbl" WHERE ("cacheCol" REGEXP ('(?<=\"26":\{)[^\{]*"qnt":"[1-9]\d*"(?=.*\})'))

出现错误:

Got error 'repetition-operator operand invalid' from regexp

这里有 sqlfiddle 可以玩:http://www.sqlfiddle.com/#!9/30335a/1 (更新 sqlfiddle 以涵盖 DB 中的更多变体)

有什么方法可以解决我的正则表达式以与 mysql 兼容。

找到一些关于具有 json 数据类型的 mysql 5.7 的信息,也许在哪里可以避免使用正则表达式来获得我想要的结果?

【问题讨论】:

  • 是的,我认为将数据类型(或转换)转换为 JSON 并使用 JSON search functions 是可行的方法。示例 SELECT * FROM tbl WHERE JSON_SEARCH( JSON_EXTRACT( CAST( cacheCol AS JSON ), "$**.qnt" ), 'all', '7' ) IS NOT NULL 搜索 qnt 为 7 的所有行。

标签: mysql json regex


【解决方案1】:

对于这样的架构:

CREATE TABLE IF NOT EXISTS `tbl` (
  `id` int(6) unsigned NOT NULL,
  `cacheCol` TEXT NOT NULL,
  PRIMARY KEY (`id`)
) DEFAULT CHARSET=utf8;
INSERT INTO `tbl` (`id`, `cacheCol`) VALUES
  ('1', '{"23":{"variationOption":"23","productCode":"322992-015","price":"150","qnt":""}}'),
  ('2', '{"25":{"variationOption":"25","productCode":"322992-015","price":"150","qnt":"0"}}'),
  ('3', '{"26":{"variationOption":"26","productCode":"322992-015","price":"150","qnt":"7"}}');

使用以下查询:

SELECT *
FROM `tbl` 
where cacheCol REGEXP '.?"qnt":"[1-9]\d*"';

由于该字段始终为 JSON 格式,因此仅搜索子字符串就足够了。

你可以玩here

如果您对此对象有很多更新和读取,那么在 Mysql 中探索 JSON 数据类型也是一个好主意,如果只是为了简单查询,那么您可以将其视为字符串并使用 REGEX 本身。

希望对你有帮助

【讨论】:

  • 太糟糕了,我的 cacheCol 包含多个 qnt 单行。检查我上面的 sqlfiddle。所以你的正则表达式不能解决我的问题:(
  • 也许 Arjithn 准备的示例与您的示例不同,但他的查询也适用于您的原始数据。 "qnt":"7" 在这两种情况下都可以找到!
  • @LinasBaublys 的解决方案对您有帮助吗?您是否能够使用此处的任何解决方案达到您想要的结果?
【解决方案2】:

您可以使用像 JSON_SEARCH() 这样的 JSON 函数来查找完全匹配但不是不等式匹配的值。

在 MySQL 8.0 中,如果您的 JSON 构造为数组,则可以使用 JSON_TABLE() 函数,但不能使用 JSON,因为您将其构造为对象。

确实,如果您需要使用不等式表达式来搜索数据中的特定字段,则根本不应该使用 JSON。您应该将数据存储在正常的行和列中。

我越是看到人们在 MySQL 中以复杂的方式滥用 JSON,我就越相信 MySQL 实现 JSON 数据类型是个坏主意。

我对 MySQL 中 JSON 的规则是:在任何地方引用 JSON 列,但 SELECT 列表是代码异味。您应该使用普通列而不是 JSON。

【讨论】:

    【解决方案3】:

    MySQL REGEXP 不支持前瞻,但您可以尝试使用以下方法实现相同的逻辑:

    SELECT * FROM "tbl" WHERE ("cacheCol" REGEXP ('(\{[\"\:,\-a-zA-Z0-9]+\"qnt\"\:\"[1-9][0-9]*\"\})'))
    
    

    希望对你有帮助。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-02-21
      • 2015-02-05
      • 1970-01-01
      • 1970-01-01
      • 2016-08-11
      • 1970-01-01
      • 2022-11-05
      • 1970-01-01
      相关资源
      最近更新 更多