MariaDB 10.2 JSON查询故障求助:含JSON_VALUE的查询语句异常
我帮你梳理一下这个查询里的几个关键问题,以及对应的修正方案:
1. WHERE子句中不能使用SELECT定义的别名
SQL的执行顺序是先处理FROM和WHERE子句,之后才会执行SELECT并生成列别名。所以你在WHERE里直接用order_row这个别名会报错,数据库根本识别不了这个字段。
修正方式:把别名对应的表达式直接写到WHERE子句里,或者用子查询/CTE先生成这个列再过滤。
2. LONGBlob类型无法直接被JSON_VALUE解析
你的cms_routing_data字段是longblob(二进制类型),而JSON_VALUE需要处理的是JSON格式的字符串数据。直接对二进制字段用JSON_VALUE会导致解析失败,因为数据库无法识别二进制内容里的JSON结构。
修正方式:先把二进制字段转换为字符类型,比如用CAST(cms_routing_data AS CHAR)或者CONVERT(cms_routing_data, CHAR CHARACTER SET utf8mb4)(可根据你的实际字符集调整)。
3. 针对Blob字段的非空判断不准确
你用cms_routing_data != ''来判断非空,但对于Blob类型来说,空字符串和空Blob(NULL)是不同的,而且直接用字符串比较符可能不符合预期。更准确的方式是用IS NOT NULL或者检查字段长度大于0:LENGTH(cms_routing_data) > 0。
修正后的完整查询语句
SELECT *, JSON_VALUE(CAST(cms_routing_data AS CHAR), "$.cms_routing_date.field") AS order_row FROM database.cms_routing WHERE cms_routing_module = 'events' AND cms_routing_data IS NOT NULL AND LENGTH(cms_routing_data) > 0 AND JSON_VALUE(CAST(cms_routing_data AS CHAR), "$.cms_routing_date.field") >= '2018-05-11' ORDER BY order_row ASC LIMIT 0,4;
如果你的数据库支持CTE(比如MySQL 8.0+),也可以用更清晰的写法,避免重复写JSON_VALUE表达式:
WITH routing_data AS ( SELECT *, JSON_VALUE(CAST(cms_routing_data AS CHAR), "$.cms_routing_date.field") AS order_row FROM database.cms_routing WHERE cms_routing_module = 'events' AND cms_routing_data IS NOT NULL AND LENGTH(cms_routing_data) > 0 ) SELECT * FROM routing_data WHERE order_row >= '2018-05-11' ORDER BY order_row ASC LIMIT 0,4;
另外还要注意:如果你的cms_routing_data里的JSON结构不统一(比如有的记录里没有cms_routing_date.field这个路径),JSON_VALUE会返回NULL,这部分数据会被order_row >= '2018-05-11'过滤掉,这是符合预期的,但如果需要保留这类数据可以调整条件。
内容的提问来源于stack exchange,提问作者J Quest

