SQL Server 2016 "FOR JSON PATH" - 修改JSON 嵌套
SQL Server 2016 "FOR JSON PATH" - Modify JSON nesting
我正在尝试使用 FOR JSON PATH
更改查询的 JSON 输出的嵌套。 FOR JSON AUTO
查询几乎是我所需要的,但不完全是。
查询使用 FOR JSON AUTO
:
SELECT
table_name = tables.name,
table_object_id = tables.object_id,
index_name = indexes.name,
index_id = indexes.index_id,
column_name = columns.name,
column_id = index_columns.index_column_id,
max_length = columns.max_length,
precision = columns.precision,
scale = columns.scale
FROM
sys.indexes indexes
INNER JOIN
sys.index_columns index_columns ON indexes.object_id = index_columns.object_id and indexes.index_id = index_columns.index_id
INNER JOIN
sys.columns columns ON index_columns.object_id = columns.object_id and index_columns.column_id = columns.column_id
INNER JOIN
sys.tables tables ON indexes.object_id = tables.object_id
WHERE tables.name LIKE 'tbl_%'
ORDER BY
tables.name, indexes.index_id, index_columns.index_column_id
FOR JSON AUTO
查询使用 FOR JSON AUTO
输出(片段):
.
.
.
{
"table_name": "tbl_Agent",
"table_object_id": 176055713,
"indexes": [
{
"index_name": "PK_Task_tbl_Agent",
"index_id": 1,
"columns": [
{
"column_name": "PartitionId",
"max_length": 4,
"precision": 10,
"scale": 0,
"index_columns": [
{
"column_id": 1
}
]
},
{
"column_name": "AgentId",
"max_length": 4,
"precision": 10,
"scale": 0,
"index_columns": [
{
"column_id": 2
}
]
}
]
},
{
"index_name": "IX_Task_tbl_Agent_PoolId_AgentName",
"index_id": 2,
"columns": [
{
"column_name": "PartitionId",
"max_length": 4,
"precision": 10,
"scale": 0,
"index_columns": [
{
"column_id": 1
}
]
},
{
"column_name": "PoolId",
"max_length": 4,
"precision": 10,
"scale": 0,
"index_columns": [
{
"column_id": 2
}
]
},
{
"column_name": "AgentName",
"max_length": 128,
"precision": 0,
"scale": 0,
"index_columns": [
{
"column_id": 3
}
]
}
]
},
{
"index_name": "IX_Task_tbl_Agent_PoolId_SessionId",
"index_id": 3,
"columns": [
{
"column_name": "PartitionId",
"max_length": 4,
"precision": 10,
"scale": 0,
"index_columns": [
{
"column_id": 1
}
]
},
{
"column_name": "PoolId",
"max_length": 4,
"precision": 10,
"scale": 0,
"index_columns": [
{
"column_id": 2
}
]
},
{
"column_name": "SessionId",
"max_length": 16,
"precision": 0,
"scale": 0,
"index_columns": [
{
"column_id": 3
}
]
}
]
}
]
},
.
.
.
每个 table 的所有索引都正确嵌套,并且在每个索引中,索引的所有列(这些是复合索引)都正确嵌套。我想做的唯一改变是取消嵌套 index_columns
,使 column_id
成为 columns
的一部分,例如:
.
.
.
"columns": [
{
"column_name": "PartitionId",
"max_length": 4,
"precision": 10,
"scale": 0,
---> "column_id": 1
},
{
"column_name": "PoolId",
"max_length": 4,
"precision": 10,
"scale": 0,
---> "column_id": 2
},
{
"column_name": "AgentName",
"max_length": 128,
"precision": 0,
"scale": 0,
---> "column_id": 3
}
]
.
.
.
当我尝试使用 FOR JSON PATH
时,它最终嵌套不正确。
查询使用 FOR JSON PATH
:
SELECT
tables.name AS [tables.table_name],
tables.object_id AS [tables.table_object_id],
indexes.name AS [tables.indexes.index_name],
indexes.index_id AS [tables.indexes.index_id],
columns.name AS [tables.indexes.columns.column_name],
index_columns.index_column_id AS [tables.indexes.columns.column_id],
columns.max_length AS [tables.indexes.columns.max_length],
columns.precision AS [tables.indexes.columns.precision],
columns.scale AS [tables.indexes.columns.scale]
FROM
sys.indexes indexes
INNER JOIN
sys.index_columns index_columns ON indexes.object_id = index_columns.object_id and indexes.index_id = index_columns.index_id
INNER JOIN
sys.columns columns ON index_columns.object_id = columns.object_id and index_columns.column_id = columns.column_id
INNER JOIN
sys.tables tables ON indexes.object_id = tables.object_id
WHERE tables.name LIKE 'tbl_%'
ORDER BY
tables.name, indexes.index_id, index_columns.index_column_id
FOR JSON PATH
查询使用 FOR JSON PATH
输出(片段):
.
.
.
{
"tables": {
===> "table_name": "tbl_Agent",
"table_object_id": 176055713,
"indexes": {
---> "index_name": "PK_Task_tbl_Agent",
"index_id": 1,
"columns": {
"column_name": "PartitionId",
"column_id": 1,
"max_length": 4,
"precision": 10,
"scale": 0
}
}
}
},
{
"tables": {
===> "table_name": "tbl_Agent",
"table_object_id": 176055713,
"indexes": {
---> "index_name": "PK_Task_tbl_Agent",
"index_id": 1,
"columns": {
"column_name": "AgentId",
"column_id": 2,
"max_length": 4,
"precision": 10,
"scale": 0
}
}
}
},
{
"tables": {
===> "table_name": "tbl_Agent",
"table_object_id": 176055713,
"indexes": {
"index_name": "IX_Task_tbl_Agent_PoolId_AgentName",
"index_id": 2,
"columns": {
"column_name": "PartitionId",
"column_id": 1,
"max_length": 4,
"precision": 10,
"scale": 0
}
}
}
},
.
.
.
虽然 column_id
现在是我希望的位置,但 columns
现在是唯一正确嵌套的东西。现在每个 table
对其每个 indexes
重复,每个 index
对其每个 columns
.
重复
如何在我想要的地方获得 column_id
(如 FOR JSON PATH
查询的输出),同时保持正确的嵌套(如 [=] 的输出22=]查询)?
更新 -- 工作中
根据 DimaSUN 的回复和 Ben 的评论,我提出了现在有效的查询:
SELECT
tables.name AS [table_name],
tables.object_id AS [table_object_id],
(SELECT
indexes.name AS [index_name],
indexes.index_id AS [index_id],
(SELECT
columns.name AS [column_name],
index_columns.index_column_id AS [column_id],
columns.max_length AS [max_length],
columns.precision AS [precision],
columns.scale AS [scale]
FROM
sys.index_columns index_columns
JOIN
sys.columns columns ON index_columns.object_id = columns.object_id and index_columns.column_id = columns.column_id
WHERE
indexes.object_id = index_columns.object_id and indexes.index_id = index_columns.index_id
ORDER BY
index_columns.index_column_id
FOR JSON PATH
) AS 'columns'
FROM
sys.indexes indexes
WHERE
indexes.object_id = tables.object_id
ORDER BY
indexes.index_id
FOR JSON PATH
) AS 'indexes'
FROM
sys.tables tables
WHERE
tables.name LIKE 'tbl_%'
ORDER BY
tables.name
FOR JSON PATH, ROOT('tables')
新查询输出(片段):
.
.
.
{
"table_name": "tbl_Agent",
"table_object_id": 176055713,
"indexes": [
{
"index_name": "PK_Task_tbl_Agent",
"index_id": 1,
"columns": [
{
"column_name": "PartitionId",
"column_id": 1,
"max_length": 4,
"precision": 10,
"scale": 0
},
{
"column_name": "AgentId",
"column_id": 2,
"max_length": 4,
"precision": 10,
"scale": 0
}
]
},
{
"index_name": "IX_Task_tbl_Agent_PoolId_AgentName",
"index_id": 2,
"columns": [
{
"column_name": "PartitionId",
"column_id": 1,
"max_length": 4,
"precision": 10,
"scale": 0
},
{
"column_name": "PoolId",
"column_id": 2,
"max_length": 4,
"precision": 10,
"scale": 0
},
{
"column_name": "AgentName",
"column_id": 3,
"max_length": 128,
"precision": 0,
"scale": 0
}
]
},
{
"index_name": "IX_Task_tbl_Agent_PoolId_SessionId",
"index_id": 3,
"columns": [
{
"column_name": "PartitionId",
"column_id": 1,
"max_length": 4,
"precision": 10,
"scale": 0
},
{
"column_name": "PoolId",
"column_id": 2,
"max_length": 4,
"precision": 10,
"scale": 0
},
{
"column_name": "SessionId",
"column_id": 3,
"max_length": 16,
"precision": 0,
"scale": 0
}
]
}
]
},
.
.
.
嵌套选择末尾的 AS 'columns'
和 AS 'indexes'
是一个关键部分,否则我会收到以下错误:
Msg 13605, Level 16, State 1, Line 1
Unnamed tables cannot be used as JSON identifiers as well as unnamed columns cannot be used as key names. Add alias to the unnamed column/table.
XML 看起来像
( select
indexes.name AS [index_name],
indexes.index_id AS [index_id],
( select
columns.name AS [column_name],
index_columns.index_column_id AS [column_id],
columns.max_length AS [max_length],
columns.precision AS [precision],
columns.scale AS [scale]
from
sys.index_columns index_columns
JOIN
sys.columns columns ON index_columns.object_id = columns.object_id and index_columns.column_id = columns.column_id
where indexes.object_id = index_columns.object_id and indexes.index_id = index_columns.index_id
FOR xml PATH(''), root('columns'), type
)
from
sys.indexes indexes
where indexes.object_id = tables.object_id
FOR xml PATH(''), root('indices'), type
)
FROM
sys.tables tables
WHERE tables.name LIKE 'tbl_%'
--ORDER BY tables.name, indexes.index_id, index_columns.index_column_id
FOR XML PATH('tables')
将 XML 替换为 JSON。
我正在尝试使用 FOR JSON PATH
更改查询的 JSON 输出的嵌套。 FOR JSON AUTO
查询几乎是我所需要的,但不完全是。
查询使用 FOR JSON AUTO
:
SELECT
table_name = tables.name,
table_object_id = tables.object_id,
index_name = indexes.name,
index_id = indexes.index_id,
column_name = columns.name,
column_id = index_columns.index_column_id,
max_length = columns.max_length,
precision = columns.precision,
scale = columns.scale
FROM
sys.indexes indexes
INNER JOIN
sys.index_columns index_columns ON indexes.object_id = index_columns.object_id and indexes.index_id = index_columns.index_id
INNER JOIN
sys.columns columns ON index_columns.object_id = columns.object_id and index_columns.column_id = columns.column_id
INNER JOIN
sys.tables tables ON indexes.object_id = tables.object_id
WHERE tables.name LIKE 'tbl_%'
ORDER BY
tables.name, indexes.index_id, index_columns.index_column_id
FOR JSON AUTO
查询使用 FOR JSON AUTO
输出(片段):
.
.
.
{
"table_name": "tbl_Agent",
"table_object_id": 176055713,
"indexes": [
{
"index_name": "PK_Task_tbl_Agent",
"index_id": 1,
"columns": [
{
"column_name": "PartitionId",
"max_length": 4,
"precision": 10,
"scale": 0,
"index_columns": [
{
"column_id": 1
}
]
},
{
"column_name": "AgentId",
"max_length": 4,
"precision": 10,
"scale": 0,
"index_columns": [
{
"column_id": 2
}
]
}
]
},
{
"index_name": "IX_Task_tbl_Agent_PoolId_AgentName",
"index_id": 2,
"columns": [
{
"column_name": "PartitionId",
"max_length": 4,
"precision": 10,
"scale": 0,
"index_columns": [
{
"column_id": 1
}
]
},
{
"column_name": "PoolId",
"max_length": 4,
"precision": 10,
"scale": 0,
"index_columns": [
{
"column_id": 2
}
]
},
{
"column_name": "AgentName",
"max_length": 128,
"precision": 0,
"scale": 0,
"index_columns": [
{
"column_id": 3
}
]
}
]
},
{
"index_name": "IX_Task_tbl_Agent_PoolId_SessionId",
"index_id": 3,
"columns": [
{
"column_name": "PartitionId",
"max_length": 4,
"precision": 10,
"scale": 0,
"index_columns": [
{
"column_id": 1
}
]
},
{
"column_name": "PoolId",
"max_length": 4,
"precision": 10,
"scale": 0,
"index_columns": [
{
"column_id": 2
}
]
},
{
"column_name": "SessionId",
"max_length": 16,
"precision": 0,
"scale": 0,
"index_columns": [
{
"column_id": 3
}
]
}
]
}
]
},
.
.
.
每个 table 的所有索引都正确嵌套,并且在每个索引中,索引的所有列(这些是复合索引)都正确嵌套。我想做的唯一改变是取消嵌套 index_columns
,使 column_id
成为 columns
的一部分,例如:
.
.
.
"columns": [
{
"column_name": "PartitionId",
"max_length": 4,
"precision": 10,
"scale": 0,
---> "column_id": 1
},
{
"column_name": "PoolId",
"max_length": 4,
"precision": 10,
"scale": 0,
---> "column_id": 2
},
{
"column_name": "AgentName",
"max_length": 128,
"precision": 0,
"scale": 0,
---> "column_id": 3
}
]
.
.
.
当我尝试使用 FOR JSON PATH
时,它最终嵌套不正确。
查询使用 FOR JSON PATH
:
SELECT
tables.name AS [tables.table_name],
tables.object_id AS [tables.table_object_id],
indexes.name AS [tables.indexes.index_name],
indexes.index_id AS [tables.indexes.index_id],
columns.name AS [tables.indexes.columns.column_name],
index_columns.index_column_id AS [tables.indexes.columns.column_id],
columns.max_length AS [tables.indexes.columns.max_length],
columns.precision AS [tables.indexes.columns.precision],
columns.scale AS [tables.indexes.columns.scale]
FROM
sys.indexes indexes
INNER JOIN
sys.index_columns index_columns ON indexes.object_id = index_columns.object_id and indexes.index_id = index_columns.index_id
INNER JOIN
sys.columns columns ON index_columns.object_id = columns.object_id and index_columns.column_id = columns.column_id
INNER JOIN
sys.tables tables ON indexes.object_id = tables.object_id
WHERE tables.name LIKE 'tbl_%'
ORDER BY
tables.name, indexes.index_id, index_columns.index_column_id
FOR JSON PATH
查询使用 FOR JSON PATH
输出(片段):
.
.
.
{
"tables": {
===> "table_name": "tbl_Agent",
"table_object_id": 176055713,
"indexes": {
---> "index_name": "PK_Task_tbl_Agent",
"index_id": 1,
"columns": {
"column_name": "PartitionId",
"column_id": 1,
"max_length": 4,
"precision": 10,
"scale": 0
}
}
}
},
{
"tables": {
===> "table_name": "tbl_Agent",
"table_object_id": 176055713,
"indexes": {
---> "index_name": "PK_Task_tbl_Agent",
"index_id": 1,
"columns": {
"column_name": "AgentId",
"column_id": 2,
"max_length": 4,
"precision": 10,
"scale": 0
}
}
}
},
{
"tables": {
===> "table_name": "tbl_Agent",
"table_object_id": 176055713,
"indexes": {
"index_name": "IX_Task_tbl_Agent_PoolId_AgentName",
"index_id": 2,
"columns": {
"column_name": "PartitionId",
"column_id": 1,
"max_length": 4,
"precision": 10,
"scale": 0
}
}
}
},
.
.
.
虽然 column_id
现在是我希望的位置,但 columns
现在是唯一正确嵌套的东西。现在每个 table
对其每个 indexes
重复,每个 index
对其每个 columns
.
如何在我想要的地方获得 column_id
(如 FOR JSON PATH
查询的输出),同时保持正确的嵌套(如 [=] 的输出22=]查询)?
更新 -- 工作中
根据 DimaSUN 的回复和 Ben 的评论,我提出了现在有效的查询:
SELECT
tables.name AS [table_name],
tables.object_id AS [table_object_id],
(SELECT
indexes.name AS [index_name],
indexes.index_id AS [index_id],
(SELECT
columns.name AS [column_name],
index_columns.index_column_id AS [column_id],
columns.max_length AS [max_length],
columns.precision AS [precision],
columns.scale AS [scale]
FROM
sys.index_columns index_columns
JOIN
sys.columns columns ON index_columns.object_id = columns.object_id and index_columns.column_id = columns.column_id
WHERE
indexes.object_id = index_columns.object_id and indexes.index_id = index_columns.index_id
ORDER BY
index_columns.index_column_id
FOR JSON PATH
) AS 'columns'
FROM
sys.indexes indexes
WHERE
indexes.object_id = tables.object_id
ORDER BY
indexes.index_id
FOR JSON PATH
) AS 'indexes'
FROM
sys.tables tables
WHERE
tables.name LIKE 'tbl_%'
ORDER BY
tables.name
FOR JSON PATH, ROOT('tables')
新查询输出(片段):
.
.
.
{
"table_name": "tbl_Agent",
"table_object_id": 176055713,
"indexes": [
{
"index_name": "PK_Task_tbl_Agent",
"index_id": 1,
"columns": [
{
"column_name": "PartitionId",
"column_id": 1,
"max_length": 4,
"precision": 10,
"scale": 0
},
{
"column_name": "AgentId",
"column_id": 2,
"max_length": 4,
"precision": 10,
"scale": 0
}
]
},
{
"index_name": "IX_Task_tbl_Agent_PoolId_AgentName",
"index_id": 2,
"columns": [
{
"column_name": "PartitionId",
"column_id": 1,
"max_length": 4,
"precision": 10,
"scale": 0
},
{
"column_name": "PoolId",
"column_id": 2,
"max_length": 4,
"precision": 10,
"scale": 0
},
{
"column_name": "AgentName",
"column_id": 3,
"max_length": 128,
"precision": 0,
"scale": 0
}
]
},
{
"index_name": "IX_Task_tbl_Agent_PoolId_SessionId",
"index_id": 3,
"columns": [
{
"column_name": "PartitionId",
"column_id": 1,
"max_length": 4,
"precision": 10,
"scale": 0
},
{
"column_name": "PoolId",
"column_id": 2,
"max_length": 4,
"precision": 10,
"scale": 0
},
{
"column_name": "SessionId",
"column_id": 3,
"max_length": 16,
"precision": 0,
"scale": 0
}
]
}
]
},
.
.
.
嵌套选择末尾的 AS 'columns'
和 AS 'indexes'
是一个关键部分,否则我会收到以下错误:
Msg 13605, Level 16, State 1, Line 1
Unnamed tables cannot be used as JSON identifiers as well as unnamed columns cannot be used as key names. Add alias to the unnamed column/table.
XML 看起来像
( select
indexes.name AS [index_name],
indexes.index_id AS [index_id],
( select
columns.name AS [column_name],
index_columns.index_column_id AS [column_id],
columns.max_length AS [max_length],
columns.precision AS [precision],
columns.scale AS [scale]
from
sys.index_columns index_columns
JOIN
sys.columns columns ON index_columns.object_id = columns.object_id and index_columns.column_id = columns.column_id
where indexes.object_id = index_columns.object_id and indexes.index_id = index_columns.index_id
FOR xml PATH(''), root('columns'), type
)
from
sys.indexes indexes
where indexes.object_id = tables.object_id
FOR xml PATH(''), root('indices'), type
)
FROM
sys.tables tables
WHERE tables.name LIKE 'tbl_%'
--ORDER BY tables.name, indexes.index_id, index_columns.index_column_id
FOR XML PATH('tables')
将 XML 替换为 JSON。