SQL 服务器:从 JSON 自动数据动态创建列名
SQL Server: Dynamically create Column Names from JSON Auto Data
我在 SQL 服务器中使用 JSONAUTO 创建了 JSON 数据。
SELECT *
from #Testdata
FOR JSON AUTO
它存储在nvarchar(max)中,并创建多个相同类型的记录。
[{"ProductId":1,"ProductName":"Food","ProductDescription":"Apple","DatePurchased":"1995-05-01T00:00:00"}, {"ProductId":2,"ProductName":"Electronics","ProductDescription":"TV","DatePurchase":"2018-09-17T00:00:00"}]
现在我想插入与 Json 字段完全相同的列名的表名。
尝试动态创建列名,以使用完全相同的列名插入 table。我将如何使用 SQL 服务器 Json 库执行此操作?
insert into dbo.SampleTable
(
ProductId,
ProductName,
ProductDescription,
DatePurchased
)
现在允许显式声明列号,从输入中,列名必须来自 Json 数据本身。以后会有未来类型的数据。
更新:
看到这个答案,想知道是否有办法绕过删除首尾字母,难道SQL服务器没有内部库函数吗?这就是我正在寻找的,同时消除了子字符串的东西,也就是删除了方括号 [ 和 ]。
declare @json NVARCHAR(MAX) = '[{"ProductId":1,"ProductName":"Food","ProductDescription":"Apple","DatePurchased":"1995-05-01T00:00:00"}, {"ProductId":2,"ProductName":"Electronics","ProductDescription":"TV","DatePurchase":"2018-09-17T00:00:00"}]'
DECLARE @jsonformatted NVARCHAR(MAX) = substring(@json, 2, len(@json)-1)
SELECT * FROM OPENJSON(@jsonformatted);
说明:
如果您不知道列名,则需要使用 OPENJSON()
和 default 架构来 return 一个 table 每个 属性 对象或数组中的每个元素。在您的情况下,您可以尝试查询 JSON
数据的第一项。
T-SQL:
SELECT [key]
FROM OPENJSON(@json, '$[0]')
输出:
-------------------
key
-------------------
ProductId
ProductName
ProductDescription
DatePurchase
示例:
如果您需要更复杂的数据操作,您可以尝试生成并执行动态语句:
JSON:
DECLARE @json nvarchar(max) = N'
[
{
"ProductId":1,
"ProductName":"Food",
"ProductDescription":"Apple",
"DatePurchased":"1995-05-01T00:00:00"
},
{
"ProductId":2,
"ProductName":"Electronics",
"ProductDescription":"TV",
"DatePurchased":"2018-09-17T00:00:00"
}
]
'
动态 INSERT 语句:
DECLARE @columns nvarchar(max) = N''
DECLARE @schema nvarchar(max) = N''
DECLARE @stm nvarchar(max)
-- Columns
SELECT
@columns = CONCAT(@columns, N',', QUOTENAME([key])),
@schema = CONCAT(@schema, N',', QUOTENAME([key]), N' varchar(max) ''$.', [key], N'''')
FROM OPENJSON(@json, '$[0]')
-- Statement
SET @stm = CONCAT(
N'INSERT INTO #TestData (',
STUFF(@columns, 1, 1, N''),
N') SELECT * FROM OPENJSON(@json) WITH (',
STUFF(@schema, 1, 1, N''),
N') json'
)
PRINT @stm
EXEC sp_executesql @stm
生成的语句:
INSERT INTO #TestData ([ProductId],[ProductName],[ProductDescription],[DatePurchased])
SELECT *
FROM OPENJSON(@json) WITH (
[ProductId] varchar(max) '$.ProductId',
[ProductName] varchar(max) '$.ProductName',
[ProductDescription] varchar(max) '$.ProductDescription',
[DatePurchased] varchar(max) '$.DatePurchased'
) json
原回答:
如果我理解正确,你需要使用 OPENJSON()
和显式模式定义。
声明:
INSERT INTO #TestData
(ProductId, ProductName, ProductDescription, DatePurchased)
SELECT *
FROM OPENJSON(@json) WITH (
ProductId varchar(100) '$.ProductId',
ProductName varchar(100) '$.ProductName',
ProductDescription varchar(100) '$.ProductDescription',
DatePurchased datetime '$.DatePurchased'
) json
DECLARE @jsonata NVARCHAR(MAX)='[{"ProductId":1,"ProductName":"Food","ProductDescription":"Apple","DatePurchase":"1995-05-01T00:00:00"}, {"ProductId":2,"ProductName":"Electronics","ProductDescription":"TV","DatePurchase":"2018-09-17T00:00:00"}]'
DECLARE @Query NVARCHAR(MAX)=N' INSERT INTO [TableName] ('
SELECT @Query+=T.ColumnName+','
FROM
(
SELECT y.[key] AS ColumnName,
x.[Key]
FROM OPENJSON(@jsonata) x
CROSS APPLY (SELECT * FROM OPENJSON(x.[value])) y
) AS T
WHERE T.[Key]=0
SET @Query=STUFF(@Query,LEN(@Query),1,' ')+' ) VALUES ('
SELECT @Query+=''''+T.Value+''''+
(CASE WHEN ISNULL(LEAD(T.[Key]) OVER(ORDER BY T.[Key]),0)=T.[Key] THEN ',' ELSE '),(' END)
FROM
(
SELECT y.[key] AS ColumnName,
y.[Value],
X.[key]
FROM OPENJSON(@jsonata) x
CROSS APPLY (SELECT * FROM OPENJSON(x.[value])) y
) AS T
SET @Query=SUBSTRING(@Query,1,LEN(@Query)-2)
--Print Query Statment
PRINT (@Query)
EXEC(@Query)
[1]: https://i.stack.imgur.com/KpNKc.png
如果你不想要它周围的数组括号,那么你可能想要
SELECT *
来自#Testdata
对于 JSON 路径,WITHOUT_ARRAY_WRAPPER
但是,请注意,如果您获得多行,那将是无效的 JSON。
我在 SQL 服务器中使用 JSONAUTO 创建了 JSON 数据。
SELECT *
from #Testdata
FOR JSON AUTO
它存储在nvarchar(max)中,并创建多个相同类型的记录。
[{"ProductId":1,"ProductName":"Food","ProductDescription":"Apple","DatePurchased":"1995-05-01T00:00:00"}, {"ProductId":2,"ProductName":"Electronics","ProductDescription":"TV","DatePurchase":"2018-09-17T00:00:00"}]
现在我想插入与 Json 字段完全相同的列名的表名。 尝试动态创建列名,以使用完全相同的列名插入 table。我将如何使用 SQL 服务器 Json 库执行此操作?
insert into dbo.SampleTable
(
ProductId,
ProductName,
ProductDescription,
DatePurchased
)
现在允许显式声明列号,从输入中,列名必须来自 Json 数据本身。以后会有未来类型的数据。
更新:
看到这个答案,想知道是否有办法绕过删除首尾字母,难道SQL服务器没有内部库函数吗?这就是我正在寻找的,同时消除了子字符串的东西,也就是删除了方括号 [ 和 ]。
declare @json NVARCHAR(MAX) = '[{"ProductId":1,"ProductName":"Food","ProductDescription":"Apple","DatePurchased":"1995-05-01T00:00:00"}, {"ProductId":2,"ProductName":"Electronics","ProductDescription":"TV","DatePurchase":"2018-09-17T00:00:00"}]'
DECLARE @jsonformatted NVARCHAR(MAX) = substring(@json, 2, len(@json)-1)
SELECT * FROM OPENJSON(@jsonformatted);
说明:
如果您不知道列名,则需要使用 OPENJSON()
和 default 架构来 return 一个 table 每个 属性 对象或数组中的每个元素。在您的情况下,您可以尝试查询 JSON
数据的第一项。
T-SQL:
SELECT [key]
FROM OPENJSON(@json, '$[0]')
输出:
-------------------
key
-------------------
ProductId
ProductName
ProductDescription
DatePurchase
示例:
如果您需要更复杂的数据操作,您可以尝试生成并执行动态语句:
JSON:
DECLARE @json nvarchar(max) = N'
[
{
"ProductId":1,
"ProductName":"Food",
"ProductDescription":"Apple",
"DatePurchased":"1995-05-01T00:00:00"
},
{
"ProductId":2,
"ProductName":"Electronics",
"ProductDescription":"TV",
"DatePurchased":"2018-09-17T00:00:00"
}
]
'
动态 INSERT 语句:
DECLARE @columns nvarchar(max) = N''
DECLARE @schema nvarchar(max) = N''
DECLARE @stm nvarchar(max)
-- Columns
SELECT
@columns = CONCAT(@columns, N',', QUOTENAME([key])),
@schema = CONCAT(@schema, N',', QUOTENAME([key]), N' varchar(max) ''$.', [key], N'''')
FROM OPENJSON(@json, '$[0]')
-- Statement
SET @stm = CONCAT(
N'INSERT INTO #TestData (',
STUFF(@columns, 1, 1, N''),
N') SELECT * FROM OPENJSON(@json) WITH (',
STUFF(@schema, 1, 1, N''),
N') json'
)
PRINT @stm
EXEC sp_executesql @stm
生成的语句:
INSERT INTO #TestData ([ProductId],[ProductName],[ProductDescription],[DatePurchased])
SELECT *
FROM OPENJSON(@json) WITH (
[ProductId] varchar(max) '$.ProductId',
[ProductName] varchar(max) '$.ProductName',
[ProductDescription] varchar(max) '$.ProductDescription',
[DatePurchased] varchar(max) '$.DatePurchased'
) json
原回答:
如果我理解正确,你需要使用 OPENJSON()
和显式模式定义。
声明:
INSERT INTO #TestData
(ProductId, ProductName, ProductDescription, DatePurchased)
SELECT *
FROM OPENJSON(@json) WITH (
ProductId varchar(100) '$.ProductId',
ProductName varchar(100) '$.ProductName',
ProductDescription varchar(100) '$.ProductDescription',
DatePurchased datetime '$.DatePurchased'
) json
DECLARE @jsonata NVARCHAR(MAX)='[{"ProductId":1,"ProductName":"Food","ProductDescription":"Apple","DatePurchase":"1995-05-01T00:00:00"}, {"ProductId":2,"ProductName":"Electronics","ProductDescription":"TV","DatePurchase":"2018-09-17T00:00:00"}]'
DECLARE @Query NVARCHAR(MAX)=N' INSERT INTO [TableName] ('
SELECT @Query+=T.ColumnName+','
FROM
(
SELECT y.[key] AS ColumnName,
x.[Key]
FROM OPENJSON(@jsonata) x
CROSS APPLY (SELECT * FROM OPENJSON(x.[value])) y
) AS T
WHERE T.[Key]=0
SET @Query=STUFF(@Query,LEN(@Query),1,' ')+' ) VALUES ('
SELECT @Query+=''''+T.Value+''''+
(CASE WHEN ISNULL(LEAD(T.[Key]) OVER(ORDER BY T.[Key]),0)=T.[Key] THEN ',' ELSE '),(' END)
FROM
(
SELECT y.[key] AS ColumnName,
y.[Value],
X.[key]
FROM OPENJSON(@jsonata) x
CROSS APPLY (SELECT * FROM OPENJSON(x.[value])) y
) AS T
SET @Query=SUBSTRING(@Query,1,LEN(@Query)-2)
--Print Query Statment
PRINT (@Query)
EXEC(@Query)
[1]: https://i.stack.imgur.com/KpNKc.png
如果你不想要它周围的数组括号,那么你可能想要
SELECT * 来自#Testdata 对于 JSON 路径,WITHOUT_ARRAY_WRAPPER
但是,请注意,如果您获得多行,那将是无效的 JSON。