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

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

我正在尝试将以下 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"
    }
  }
,

这是我试图修复的 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

这是 table.

中的结果
RECORDNO                        BATCH_DATE
264378-1756289-919567--accrual  2022-02-01 00:00:00.0000000

我认为这与“CROSS APPLY and OPENJSON”的位置有关,但我不确定如何解决它。

更新:

我在应用 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

这是 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();
            }
        }

这是因为您的 JSON 有多个根节点,所以 SQL 服务器只获取第一个。我们可以通过以下方式看到这一点:

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)

注意只拾取了一组,对于 GLDETAIL,不是 2。

我们可以通过将数据放入数组中来“解决”这个问题:

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;

在编辑您的 post 之前,将 Json 放入“[ ]”即可解决问题。 而且我认为你甚至不需要 CROSS APPLY OPENJSON (@JSON)。查询将是这样的:

    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