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。

参见微软文档: https://docs.microsoft.com/en-us/sql/relational-databases/json/remove-square-brackets-from-json-without-array-wrapper-option?view=sql-server-ver15