有没有办法强制条件执行顺序(在where子句中) 我想先强制mssql过滤行
ISJSON(Data)=1
,然后JSON_VALUE...
我有这个疑问:
SELECT *,
ISJSON(Data) p
FROM dbo.Table
WHERE ISJSON(Data) = 1 AND JSON_VALUE(Data, '$.F1.F2') IS NOT NULL;
并且我在“数据”列中没有有效 json 的行中遇到错误
JSON text is not properly formatted. Unexpected character '.' is found at position 12.
我尝试过滤子查询中的行,但没有帮助,因为查询计划改变了执行顺序:
SELECT *,
ISJSON(Data) p
FROM
(SELECT * FROM dbo.Table WHERE ISJSON(Data) = 1) q
WHERE JSON_VALUE(Data, '$.F1.F2') IS NOT NULL;
临时解决方案是:
SELECT *,
ISJSON(Data) p
FROM
(SELECT *,IIF(ISJSON(Data) =1,Data,'{}') JData FROM dbo.Table WHERE ISJSON(Data) = 1) q
WHERE JSON_VALUE(JData, '$.F1.F2') IS NOT NULL;
但这不是最佳解决方案
记住这一事实: 服务器可以根据需要自由地重新排序
WHERE
和 JOIN
条件,包括推送子查询。
因此,您第一次尝试使用子查询只不过是侥幸,并且可能随时中断。
保证不会发生重新排序的唯一方法是使用
CASE
表达式或派生词,例如NULLIF
和IIF
。 (即便如此,您也只能使用标量表达式,而不能使用聚合函数。)
这就是您的最终选择有效的原因。这是唯一有保证的方法。您可以将其简化如下:
SELECT *,
ISJSON(Data) p
FROM dbo.Table
WHERE JSON_VALUE(CASE WHEN ISJSON(Data) = 1 THEN Data END, '$.F1.F2') IS NOT NULL;
将
NULL
传递给 JSON_VALUE
只会让你返回 NULL
,所以这应该总是有效。