Rol*_*rag 5 t-sql sql-server arrays json sql-server-2016
我正在尝试使用 SQL Server 2016 构建一个包含数组的 JSON 对象。
数组的源数据本身就是 JSON,因此我在JSON_QUERYselect 语句内部使用,并将 FOR JSON 子句应用于该 select 语句。
一切都工作得很好,直到我将JSON_QUERY子句包装在CASE语句中(在某些情况下不得包含数组,即必须为空)。
下面的代码说明了这个问题:
declare @projects nvarchar(max) = '{"projects": [23439658267415,166584258534050]}'
declare @id bigint = 123
SELECT
[data.array1] = JSON_QUERY(@projects, '$.projects') -- returns an array - perfect.
, [data.array2] = CASE WHEN 1 is NOT NULL
THEN JSON_QUERY(@projects, '$.projects')
ELSE NULL END -- returns an array - still good!
, [data.array3] = CASE WHEN @id is NOT NULL
THEN JSON_QUERY(@projects, '$.projects')
ELSE NULL END -- why do I end up with a string in the JSON when I do this?
FOR JSON PATH, without_array_wrapper
Run Code Online (Sandbox Code Playgroud)
此代码返回以下 JSON:
{
"data":{
"array1": [23439658267415,166584258534050],
"array2": [23439658267415,166584258534050],
"array3":"[23439658267415,166584258534050]"
}
}
Run Code Online (Sandbox Code Playgroud)
问题是第三个“数组”作为字符串对象返回。
我希望它返回以下 JSON:
{
"data":{
"array1": [23439658267415,166584258534050],
"array2": [23439658267415,166584258534050],
"array3": [23439658267415,166584258534050]
}
}
Run Code Online (Sandbox Code Playgroud)
如果我删除该FOR JSON PATH...子句,则查询返回的所有列都相同(即函数返回的所有三个 nvarchar 值JSON_QUERY都相同)。
为什么会发生这种情况,如何让它在最终的 JSON 中输出数组?
将 case 语句的结果包装在对 的调用中JSON_QUERY。
, [data.array3] = JSON_QUERY(
CASE WHEN @id is NOT NULL
THEN JSON_QUERY(@projects, '$.projects')
ELSE NULL END
)
Run Code Online (Sandbox Code Playgroud)
根据文档JSON_QUERY“从 JSON 字符串中提取对象或数组”。再往下,它说“返回 nvarchar(max) 类型的 JSON 片段。”。有点混乱。
for xml json对字符串值执行 a 操作会在返回的 JSON 字符串中提供一个字符串值,当您对 JSON 对象执行此操作时,您会得到内联到结果字符串值中的 JSON 对象。
您可以将 CASE 视为一个函数调用,通过查看从 CASE 返回的值,自动确定返回值。由于 JSON_QUERY 返回一个字符串,因此 case 将返回一个字符串,并且返回的值将是 JSON 中的字符串值。
查询计划中的 case 语句如下所示。
<ScalarOperator ScalarString="CASE WHEN [@id] IS NOT NULL THEN json_query([@projects],N'$.projects') ELSE NULL END">
Run Code Online (Sandbox Code Playgroud)
当您将案例包装在对 JSON_QUERY 的调用中时,它看起来像这样。
<ScalarOperator ScalarString="json_query(CASE WHEN [@id] IS NOT NULL THEN json_query([@projects],N'$.projects') ELSE NULL END)">
<Intrinsic FunctionName="json_query">
Run Code Online (Sandbox Code Playgroud)
通过某种内部魔法,SQL Server 将其识别为 JSON 对象而不是字符串,并将其作为 JSON 值插入到生成的 JSON 字符串中。
CASE WHEN 1 is NOT NULL之所以有效,是因为 SQL Server 足够聪明,可以看到 case 语句始终为 true,并且已被优化掉。
| 归档时间: |
|
| 查看次数: |
3206 次 |
| 最近记录: |