解析 JSON 数据并插入到 SQL Server 中的多个表中

Posted

技术标签:

【中文标题】解析 JSON 数据并插入到 SQL Server 中的多个表中【英文标题】:Parse JSON data and insert into multiple tables in SQL Server 【发布时间】:2021-07-07 08:19:26 【问题描述】:

我有一个 JSON,其中包含以下格式的客户信息


  "customerdata": [
    
      "customerID": "abcsd112-1234-4c01-abcd-bb2fb084dc52",
      "customerDetails": [
        
          "fieldId": "100",
          "fieldValue": "ABC"
        ,
        
          "fieldId": "101",
          "fieldValue": "TESTCUSTOMER001"
        ,
        
          "fieldId": "102",
          "fieldValue": "1000"
        ,
        
          "fieldId": "103",
          "fieldValue": "TESTNAME"
             
            
      ]
    ,
    
      "customerID": "cdfsd112-4c01-45d7-abcd-9c9662d4ca30",
      "customerDetails": [
        
          "fieldId": "100",
          "fieldValue": "CDE"
        ,
        
          "fieldId": "101",
          "fieldValue": "TESTCUSTOMER002"
        ,
        
          "fieldId": "102",
          "fieldValue": "1002"
        ,
        
          "fieldId": "103",
          "fieldValue": "TESTNAME2"
            
      ]
        
  ]

从这个 JSON 数据中,我想将数据插入两个单独的表中。这样,客户 ID 详细信息到一个表 (CustomerDetails) 和客户字段详细信息 (customerDetails json 节点) 到另一个表 (CustomerFieldData) 的外键引用第一个表(客户 ID)。

所以下面是需要的表格

    CustomerDetails 表结构,其中来自 JSON 的 customerID 应插入到 CustomerUniqueGUID 列,客户名称将来自 customerDetails json 节点的字段 id 101
    CREATE TABLE [CustomerDetails](
    [CustomerID] [bigint] IDENTITY(1,1) NOT NULL PRIMARY KEY,
    [CustomerUniqueGUID] UNIQUEIDENTIFIER NOT NULL,
    [CustomerName] [varchar](100) NULL, 
    [IsActive] [bit] NULL)
    
    客户字段数据表
    CREATE TABLE [CustomerFieldData](
        [CustomerFieldDataID] [bigint] IDENTITY(1,1) NOT NULL PRIMARY KEY,
        [CustomerID] [bigint] NOT NULL FOREIGN KEY REFERENCES [CustomerDetails] ([CustomerID]), 
        [FieldID] [varchar](100) NOT NULL,
        [FieldValue] [varchar](100) NOT NULL)
    

我已经创建了一个示例存储过程来做同样的事情。

ALTER PROCEDURE [InsertCustomerInfo]
    @CustomerJson NVarchar(MAX) 
AS
BEGIN
      
        INSERT INTO CustomerDetails (CustomerUniqueGUID,CustomerName)
        SELECT Customer.customerID, Fields.fieldValue FROM 
        OPENJSON(@CustomerJson)
                        WITH ([customerdata] nvarchar(max) as json
                        ) AS CustomerBatch
                        cross apply openjson (CustomerBatch.[customerdata])
                        with
                        (
                            customerID varchar(100),
                            customerDetails nvarchar(max) as json
                        ) AS Customer
                        cross apply openjson (Customer.customerDetails) with
                        (   
                            fieldId nvarchar(100),
                            fieldValue nvarchar(max)
                        ) as Fields
                        WHERE Fields.fieldID='101'              
        AND CustomerDetails.CustomerUniqueGUID not in (SELECT CustomerUniqueGUID FROM CustomerDetails WHERE ISActive=1 )

                
        If @@ROWCOUNT > 0               
        BEGIN
            INSERT INTO [CustomerFieldData](CustomerID,FieldID,FieldValue) SELECT L.CustomerID,Fields.fieldId,Fields.fieldValue FROM    
            CustomerDetails L INNER JOIN  
            OPENJSON(@CustomerJson)
            WITH ([customerdata] nvarchar(max) as json
            ) AS CustomerBatch
            cross apply openjson (CustomerBatch.[customerdata])
            with
            (   customerID varchar(100),
                customerDetails nvarchar(max) as json
            ) AS Customer
            cross apply openjson (Customer.customerDetails) with
            (   
                fieldId nvarchar(100),
                fieldValue nvarchar(max)
            ) as Fields
            ON L.CustomerUniqueGUID=Customers.customerID
                                        

        END  
    
END

但是到 CustomerFieldData 的数据没有正确发生并且需要更多时间。我的脚本有问题吗?请帮忙。

【问题讨论】:

为什么CustomerUniqueGUIDvarchar(100) 而不是uniqueidentifier @Larnu:它是一个 guid,它将是字母数字 这不能回答我的问题... 'cdfsd112-4c01-45d7-abcd-9c9662d4ca30' 的值显然是一个 GUID,那么为什么将 CustomerUniqueGUID 定义为 varchar(100)?跨度> @Larnu: uniqueidentifier 是可用的数据类型吗? 是的...从我记事起就一直存在。 【参考方案1】:

您可以在此处使用 INSERTOUTPUT 来获取新 ID 和 GUID 的值:

DECLARE @JSON nvarchar(MAX) = N'
  "customerdata": [
    
      "customerID": "abcsd112-1234-4c01-abcd-bb2fb084dc52",
      "customerDetails": [
        
          "fieldId": "100",
          "fieldValue": "ABC"
        ,
        
          "fieldId": "101",
          "fieldValue": "TESTCUSTOMER001"
        ,
        
          "fieldId": "102",
          "fieldValue": "1000"
        ,
        
          "fieldId": "103",
          "fieldValue": "TESTNAME"
             
            
      ]
    ,
    
      "customerID": "cdfsd112-4c01-45d7-abcd-9c9662d4ca30",
      "customerDetails": [
        
          "fieldId": "100",
          "fieldValue": "CDE"
        ,
        
          "fieldId": "101",
          "fieldValue": "TESTCUSTOMER002"
        ,
        
          "fieldId": "102",
          "fieldValue": "1002"
        ,
        
          "fieldId": "103",
          "fieldValue": "TESTNAME2"
            
      ]
        
  ]
';

CREATE TABLE #CustomerIDs (CustomerID bigint,
                           CustomerUniqueGUID varchar(100)) ;

INSERT INTO dbo.CustomerDetails (CustomerUniqueGUID,CustomerName)
OUTPUT inserted.CustomerID, inserted.CustomerUniqueGUID
INTO #CustomerIDs
SELECT OJ.customerID,
       CD.fieldValue
FROM OPENJSON(@JSON,'$.customerdata')
     WITH(customerID varchar(100), 
          customerDetails nvarchar(MAX) AS JSON) OJ
     CROSS APPLY OPENJSON(OJ.customerDetails)
                 WITH(fieldId int,
                      fieldValue varchar(100)) CD
WHERE CD.fieldID = 101;


INSERT INTO dbo.CustomerFieldData (CustomerID,FieldID,FieldValue)
SELECT CI.CustomerID,
       CD.fieldID,
       CD.fieldValue
FROM OPENJSON(@JSON,'$.customerdata')
     WITH (customerID varchar(100), --Let's use the right data type again
           customerDetails nvarchar(MAX) AS JSON) OJ
     CROSS APPLY OPENJSON(OJ.customerDetails)
                 WITH(fieldId int,
                      fieldValue varchar(100)) CD
     JOIN #CustomerIDs CI ON OJ.customerID = CI.CustomerUniqueGUID



DROP TABLE #CustomerIDs;
GO
SELECT *
FROM dbo.CustomerDetails;

SELECT *
FROM dbo.CustomerFieldData;

【讨论】:

以上是关于解析 JSON 数据并插入到 SQL Server 中的多个表中的主要内容,如果未能解决你的问题,请参考以下文章

使用 c# asp.net 获取 XML 数据并插入到 sql server

使用 C# 和 OPENJSON 将 JSON 插入 SQL Server 2016

JSON SQL Server 2016 解析

在 SQL Server 2008R2 中解析 Json 并计算值

创建触发器后的 SQL Server

检索 ODBC 表并插入 SQL Server CE 数据库