动态查询中多次调用ISJSON触发JSON格式错误问题
问题根因
SQL Server 查询优化器不保证WHERE子句中谓词的执行顺序,也不保证AND/OR逻辑的短路求值会按照代码书写顺序执行,所有执行顺序都会基于成本估算动态调整。
第一种写法报错的原因
你的第一个查询的WHERE条件是两个OR连接的独立子句:
WHERE (ISJSON(Properties) > 0 AND JSON_VALUE(Properties, '$._imps') = 'true') OR (ISJSON(Properties) > 0 AND JSON_VALUE(Properties, '$._imps') = 'false')
优化器在做执行计划成本评估时,会认为JSON_VALUE(Properties, '$._imps')是两个子句的公共计算项,会优先提取出来对全表所有行批量计算,之后再执行ISJSON(Properties) > 0的过滤逻辑。此时一旦扫描到Properties为非法JSON的行,就会直接触发13609错误。
第二种写法不报错的原因
第二个查询的WHERE条件是顶层AND的结构:
WHERE ISJSON(Properties) > 0 AND ( JSON_VALUE(Properties, '$._imps') = 'true' OR JSON_VALUE(Properties, '$._imps') = 'false' )
这种结构下优化器会优先执行过滤性更高、计算成本更低的ISJSON(Properties) > 0谓词,先把所有非法JSON的行从结果集中排除,后续仅对剩下的合法JSON行执行JSON_VALUE计算,自然不会触发格式错误。
更稳定的动态查询方案
如果你的查询是动态生成的,无法保证每次都能把ISJSON条件放在顶层,建议直接使用TRY_JSON_VALUE替代JSON_VALUE:该函数遇到非法JSON时只会返回NULL,不会抛出错误,兼容任意谓词排列顺序:
-- 示例,无需额外加ISJSON判断也不会报错 WHERE TRY_JSON_VALUE(Properties, '$._imps') IN ('true', 'false')
内容的提问来源于stack exchange,提问作者LennieHarvey
相关产品推荐
相关产品推荐

