Arrays 在SQL Server中遍历对象数组并获取错误:JSON文本格式不正确

Arrays 在SQL Server中遍历对象数组并获取错误:JSON文本格式不正确,arrays,json,sql-server,tsql,ssms,Arrays,Json,Sql Server,Tsql,Ssms,我试图在JSON object@files中循环遍历一个对象数组, 并将数组中的每个对象插入到表中,但我得到以下错误: JSON文本格式不正确。在位置0处发现意外字符“.” JSON使用JSONLint是有效的,所以我知道它不是我声明的对象,除非我错了。选择错误时,会在OPENJSON WITH语句中突出显示此错误: 文件名NVARCHAR100'$.fileName' 试试这个: ALTER PROCEDURE files_uploadAll @document_id INT OUTPUT,

我试图在JSON object@files中循环遍历一个对象数组, 并将数组中的每个对象插入到表中,但我得到以下错误:

JSON文本格式不正确。在位置0处发现意外字符“.”

JSON使用JSONLint是有效的,所以我知道它不是我声明的对象,除非我错了。选择错误时,会在OPENJSON WITH语句中突出显示此错误:

文件名NVARCHAR100'$.fileName'

试试这个:

ALTER PROCEDURE files_uploadAll

@document_id INT OUTPUT,
@files NVARCHAR(MAX)



AS
BEGIN

INSERT INTO documents
    (note_id, document_title, file_name, file_extension, mime_type, document_type_cd, user_id, url)
    SELECT note_id, document_title, file_name, file_extension, mime_type, document_type_cd, user_id, url
    FROM OPENJSON(@files)
    WITH (
        note_id INT '$.noteId',
        document_title NVARCHAR(100) '$.documentTitle',
        file_name NVARCHAR(100) '$.fileName',
        file_extension NVARCHAR(25) '$.fileExtension',
        mime_type NVARCHAR(50) '$.mimeType',
        document_type_cd CHAR(5) '$.documentTypeCd',
        user_id int '$.userId',
        url NVARCHAR(1000) '$.url'
    )
    SET @document_id=SCOPE_IDENTITY()

END
执行:

DECLARE @d INT
DECLARE @f NVARCHAR(MAX) = N'[
      {  
            "noteId": 1,
            "documentTitle": "doc1",
            "fileName": "doc1.pdf",
            "fileExtension": "pdf",
            "mimeType": "application/pdf",
            "documentTypeCd": "MSA",
            "userId": 1,
            "url": "http://www.url.com"
       },
       {  
            "noteId": 2,
            "documentTitle": "doc2",
            "fileName": "doc2.doc",
            "fileExtension": "doc",
            "mimeType": "application/msword",
            "documentTypeCd": "MSA",
            "userId": 1,
            "url": "http://www.url.com"
       }
    ]';
 EXECUTE files_uploadAll @files=@f, @document_id=@d OUTPUT

这里,如果您注意到我刚刚添加了array作为param&没有循环,我们可以插入具有性能的数据。

由于JSON中有根元素,您需要使用根元素调用OPENJSON,如下所示。您现在不会得到错误


不需要任何循环,也不需要更改输入。这可以通过以下查询轻松解决:

SELECT *
FROM OPENJSON(JSON_QUERY(@files,'$.files'))
WITH (
    note_id INT '$.noteId',
    document_title NVARCHAR(100) '$.documentTitle',
    file_name NVARCHAR(100) '$.fileName',
    file_extension NVARCHAR(25) '$.fileExtension',
    mime_type NVARCHAR(50) '$.mimeType',
    document_type_cd CHAR(5) '$.documentTypeCd',
    user_id int '$.userId',
    url NVARCHAR(1000) '$.url'
);
返回是一个简单的结果集,可用于任何操作:

+---------+----------------+-----------+----------------+--------------------+------------------+---------+--------------------+
| note_id | document_title | file_name | file_extension | mime_type          | document_type_cd | user_id | url                |
+---------+----------------+-----------+----------------+--------------------+------------------+---------+--------------------+
| 1       | doc1           | doc1.pdf  | pdf            | application/pdf    | MSA              | 1       | http://www.url.com |
+---------+----------------+-----------+----------------+--------------------+------------------+---------+--------------------+
| 2       | doc2           | doc2.doc  | doc            | application/msword | MSA              | 1       | http://www.url.com |
+---------+----------------+-----------+----------------+--------------------+------------------+---------+--------------------+

我使用JSON_查询进入$文件。OPENJSON将返回对象数组,而WITH子句将对象转换为命名和类型化列。

这是SQL server 2017&compatibility level 130或更高版本吗?您要求他们更改json文件。您必须为他们的json文件提供解决方案。不更改json,而是删除冗余包装,作为一个开发人员,我们知道在应用层删除它更容易、更高效,因为序列化是在一个实体中完成的,该实体具有名为files的文件集合。只需向db发送一个级别,在应用程序级别上什么都不做。若代码无法更改,我可以更改答案,但这样更有效,我必须强烈反对!1在查询级别很容易解决这个问题,请参见我的答案。2通常我们无法更改发送应用程序。3更常见的情况是,我们不想更改发送应用程序。4我们不想混合使用不同风格的数据5和(可能的)现有数据6,如果这个包装是多余的,你不知道。公平地说,这两个都是假设。取决于您的看法,我从ui到代码再到db端到端地工作,因此在调用存储过程中删除冗余包装似乎更具性能,因为从长远来看,我们必须维护混乱,所以需要对obj.files而不是obj.files进行类更改。在进行性能调整时,始终只发送您需要的内容。这非常有效!通过移除包装器,处理数据变得容易得多,并且可以轻松地将其添加到我的表中。谢谢这可能可行,但OPENJSON将返回一个表,这对于根元素来说是相当大的开销。你可能想看看我的答案。最好在这个返回值上使用JSON_查询,然后使用OPENJSON。这对返回结果集很有效,但我需要将数据插入到包含外键的表中,所以我使用了下面的Pranav解决方案。我发现移除包装器不会干扰我将要发送的数据。@hypnagogia您可以直接从此语句一次插入所有内容吗?通常这样的事情是针对一个临时表2-step-import完成的。它确实起了作用,我能够通过使用AJAX调用多路复用将数据插入表中,我发送了一个带有对象数组的请求,并以正确的顺序获取了所有数据。
SELECT *
FROM OPENJSON(JSON_QUERY(@files,'$.files'))
WITH (
    note_id INT '$.noteId',
    document_title NVARCHAR(100) '$.documentTitle',
    file_name NVARCHAR(100) '$.fileName',
    file_extension NVARCHAR(25) '$.fileExtension',
    mime_type NVARCHAR(50) '$.mimeType',
    document_type_cd CHAR(5) '$.documentTypeCd',
    user_id int '$.userId',
    url NVARCHAR(1000) '$.url'
);
+---------+----------------+-----------+----------------+--------------------+------------------+---------+--------------------+
| note_id | document_title | file_name | file_extension | mime_type          | document_type_cd | user_id | url                |
+---------+----------------+-----------+----------------+--------------------+------------------+---------+--------------------+
| 1       | doc1           | doc1.pdf  | pdf            | application/pdf    | MSA              | 1       | http://www.url.com |
+---------+----------------+-----------+----------------+--------------------+------------------+---------+--------------------+
| 2       | doc2           | doc2.doc  | doc            | application/msword | MSA              | 1       | http://www.url.com |
+---------+----------------+-----------+----------------+--------------------+------------------+---------+--------------------+