简体   繁体   English

如何将多个 JSON 行插入到 T-SQL 表中

[英]How to insert multiple JSON rows into a T-SQL table

I am trying to insert following JSON document into T-SQL:我正在尝试将以下 JSON 文档插入到 T-SQL 中:

  {
    "GLDETAIL": {
      "RECORDNO": "264378-1756289-919567--accrual",
      "BATCH_DATE": "02/01/2022"
    }
  },
  {
    "GLDETAIL": {
      "RECORDNO": "264378-1756290-919568--accrual",
      "BATCH_DATE": "02/01/2022"
    }
  }
,
  {
    "GLDETAIL": {
      "RECORDNO": "264379-1756291-919569--accrual",
      "BATCH_DATE": "02/01/2022"
    }
  },
  {
    "GLDETAIL": {
      "RECORDNO": "264379-1756292-919570--accrual",
      "BATCH_DATE": "02/01/2022"
    }
  }
,

This is T-SQL stored procedure that I was trying to fix, but only it inserted one row instead of four.这是我试图修复的 T-SQL 存储过程,但它只插入了一行而不是四行。

CREATE PROCEDURE [dbo].[InsertPerfCounterData1]

@json NVARCHAR(max)

AS
BEGIN

INSERT INTO dbo.PerfCounter2 (
  [RECORDNO]
 ,[BATCH_DATE]

)
SELECT
    RECORDNO,
    BATCH_DATE
    
FROM OPENJSON(@json) 
CROSS APPLY OPENJSON (@json)

WITH (

    RECORDNO     VARCHAR(MAX) '$.GLDETAIL.RECORDNO',
    BATCH_DATE   DATETIME2(7) '$.GLDETAIL.BATCH_DATE'
) AS jsonValues

END

This is result inside table.这是表内的结果。

RECORDNO                        BATCH_DATE
264378-1756289-919567--accrual  2022-02-01 00:00:00.0000000

I believe it is something to do with where it has "CROSS APPLY and OPENJSON", but I am not sure how to fix it.我相信这与它具有“CROSS APPLY and OPENJSON”的位置有关,但我不确定如何修复它。

Update :更新

I got this error after I applied the new SQL script that Larnu provided below:我在应用 Larnu 在下面提供的新 SQL 脚本后收到此错误:

在此处输入图像描述

System.Data.SqlClient.SqlException
  HResult=0x80131904
  Message=JSON text is not properly formatted. Unexpected character ']' 
 is found at position 501.
  Source=Core .Net SqlClient Data Provider

This is C# code:这是 C# 代码:

     using (SqlConnection conn = new SqlConnection(connString))
            {
                conn.Open();
                using (SqlCommand cmd = new SqlCommand(sprocname, conn))
                {
                    // Set command object as a stored procedure
                    cmd.CommandType = CommandType.StoredProcedure;

                    // Add parameter that will be passed to stored procedure
                    cmd.Parameters.Add(new SqlParameter(paramName, paramValue));

                cmd.ExecuteReader();
            }
        }

在此处输入图像描述

This is because your JSON has multiple root nodes, and so SQL Server is only picking up the first.这是因为你的 JSON 有多个根节点,所以 SQL Server 只接第一个。 We can see this with the following:我们可以通过以下方式看到这一点:

DECLARE @JSON nvarchar(MAX) = N'{
    "GLDETAIL": {
      "RECORDNO": "264378-1756289-919567--accrual",
      "BATCH_DATE": "02/01/2022"
    }
  },
  {
    "GLDETAIL": {
      "RECORDNO": "264378-1756290-919568--accrual",
      "BATCH_DATE": "02/01/2022"
    }
  }';

SELECT *
FROM OPENJSON(@JSON)

Notice only one set is picked up, for GLDETAIL, not 2.请注意,对于 GLDETAIL,只拾取了一组,而不是 2 组。

We can "fix" this by making the data inside an array:我们可以通过将数据放入数组来“修复”这个问题:

DECLARE @JSON nvarchar(MAX) = N'{
    "GLDETAIL": {
      "RECORDNO": "264378-1756289-919567--accrual",
      "BATCH_DATE": "02/01/2022"
    }
  },
  {
    "GLDETAIL": {
      "RECORDNO": "264378-1756290-919568--accrual",
      "BATCH_DATE": "02/01/2022"
    }
  }
,
  {
    "GLDETAIL": {
      "RECORDNO": "264379-1756291-919569--accrual",
      "BATCH_DATE": "02/01/2022"
    }
  },
  {
    "GLDETAIL": {
      "RECORDNO": "264379-1756292-919570--accrual",
      "BATCH_DATE": "02/01/2022"
    }
  }';

SELECT GLD.RECORDNO,
       GLD.BATCH_DATE
FROM OPENJSON(CONCAT('[',@JSON,']')) OJ
     CROSS APPLY OPENJSON(OJ.[value],'$.GLDETAIL')
                  WITH (RECORDNO varchar(30),--USe an appropriate length, not MAX
                        BATCH_DATE date) GLD;

Before editing your post, the problem would solved by putting the Json in "[ ]".在编辑您的帖子之前,将 Json 放入“[]”即可解决问题。 And I think you even don't need CROSS APPLY OPENJSON (@JSON) .而且我认为您甚至不需要CROSS APPLY OPENJSON (@JSON) The Query will be like this:查询将是这样的:

    DECLARE @JSON nvarchar(MAX) =  N'
    {"GLDETAIL": {"RECORDNO": "264378-1756289-919567--accrual", "BATCH_DATE": "02/01/2022"}},
    {"GLDETAIL": {"RECORDNO": "264378-1756290-919568--accrual", "BATCH_DATE": "02/01/2022"}},
    {"GLDETAIL": {"RECORDNO": "264379-1756291-919569--accrual", "BATCH_DATE": "02/01/2022"}},
    {"GLDETAIL": {"RECORDNO": "264379-1756292-919570--accrual", "BATCH_DATE": "02/01/2022"}}';
    
    INSERT INTO dbo.PerfCounter2 (
      [RECORDNO]
     ,[BATCH_DATE]
    )
    
    SELECT RECORDNO, BATCH_DATE
    FROM OPENJSON((CONCAT('[',@JSON,']'))) 
    --CROSS APPLY OPENJSON (@JSON)
    WITH (
        RECORDNO     VARCHAR(30) '$.GLDETAIL.RECORDNO', --Use also an appropriate length, not MAX 
        BATCH_DATE   DATETIME2(7) '$.GLDETAIL.BATCH_DATE'
    ) AS jsonValues

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM