【问题标题】:How to update a specific item of an array in json object如何更新 json 对象中数组的特定项
【发布时间】:2017-04-27 08:12:22
【问题描述】:

我正在处理 SQL Azure 表/数据库中的 JSON 列,JSON 对象是这样形成的:

{
  "statusId": "5A5BC717-F33A-42A5-8E48-99531C30EC87",
  "creationDateTime": "",
  "assignations": [
    {
      "userId": "CA3B0589-B558-4FCC-93A6-560754D324FC",
      "dateTime": "",
      "isCurrentAssigned": false
    },
    {
      "userId": "CA3B0589-B558-4FCC-93A6-560754D325E8",
      "dateTime": "",
      "isCurrentAssigned": false
    },
    {
      "userId": "CA3B0589-B558-4FCC-93A6-560754D347N",
      "dateTime": "",
      "isCurrentAssigned": true
    }
  ]
}

我想要完成的是在数组“assignations”中找到一个特定元素,然后更新它的一些属性,就像:

UPDATE MyTable
SET JsonData = JSON_MODIFY(JsonData, '$.assignations.isCurrentAssigned', CONVERT(BIT, 0))
FROM MyDb
WHERE JSON_VALUE(JsonData, '$.assignations.isCurrentAssigned') = CONVERT(BIT, 1) AND
JSON_VALUE(JsonData, '$.assignations.userId') =  CONVERT(UNIQUEIDENTIFIER, 'CA3B0589-B558-4FCC-93A6-560754D347N')

当然,这个 T-SQL 不工作,我将不胜感激任何帮助

【问题讨论】:

标签: tsql azure-sql-database sql-server-2016


【解决方案1】:

我找到了一个“简单的解决方法”来处理这个问题,也许它不是最好的解决方案,但我需要一个快速的解决方案,而且这很有效。

基本上我将数组转换为 T-SQL 表,根据需要更新该表上的记录,然后将该表转换为 JSON 数组,并用该数组替换原始数组。

示例代码:

DECLARE @SomeJSON NVARCHAR(MAX) = 
'{
  "statusId": "5A5BC717-F33A-42A5-8E48-99531C30EC87",
  "creationDateTime": "abc",
  "assignations": [
    {
      "userId": "5A5BC717-F33A-42A5-8E48-99531C30EC87",
      "creationDateTime": "",
      "isCurrentAssigned": false
    },
    {
      "userId": "5A5BC717-F33A-42A5-8E48-99531C30EC87",
      "creationDateTime": "",
      "isCurrentAssigned": false
    },
    {
      "userId": "5A5BC717-F33A-42A5-8E48-99531C30EC87",
      "creationDateTime": "",
      "isCurrentAssigned": true
    }
  ]
}'


DECLARE @TblAssignations TABLE
(
userId UNIQUEIDENTIFIER NULL,
creationDateTime DATETIME NULL,
isCurrentAssigned BIT NULL
)

INSERT INTO @TblAssignations
SELECT *
FROM OPENJSON(@SomeJSON, '$.assignations')
WITH(userId UNIQUEIDENTIFIER, creationDateTime DATETIME, isCurrentAssigned BIT)

UPDATE @TblAssignations
SET isCurrentAssigned = 0
WHERE userId = '5A5BC717-F33A-42A5-8E48-99531C30EC87' AND
isCurrentAssigned = 1

INSERT INTO @TblAssignations
VALUES
(
'5A5BC717-F33A-42A5-8E48-99531C30EC87',
'',
1
)

DECLARE @NewParentAssignations NVARCHAR(MAX) = (SELECT * FROM @TblAssignations FOR JSON PATH)

SET @SomeJSON = JSON_MODIFY(@SomeJSON, '$.assignations', JSON_QUERY(@NewParentAssignations))

SELECT @SomeJSON

【讨论】:

    【解决方案2】:

    我们必须在工作中做类似的事情,并最终采用与您最终使用的方法类似的方法,尽管我们在读取 JSON 时直接进行处理,以避免使用临时表或表变量。

      DECLARE @SomeJSON NVARCHAR(MAX) = 
        '{
          "statusId": "5A5BC717-F33A-42A5-8E48-99531C30EC87",
          "creationDateTime": "abc",
          "assignations": [
            {
              "userId": "5A5BC717-F33A-42A5-8E48-99531C30EC87",
              "creationDateTime": "",
              "isCurrentAssigned": false
            },
            {
              "userId": "5A5BC717-F33A-42A5-8E48-99531C30EC87",
              "creationDateTime": "",
              "isCurrentAssigned": false
            },
            {
              "userId": "5A5BC717-F33A-42A5-8E48-99531C30EC87",
              "creationDateTime": "",
              "isCurrentAssigned": true
            }
          ]
        }'
    
        DECLARE @NewParentAssignations NVARCHAR(MAX) = (
            SELECT * 
            FROM (
    
                SELECT --the update is done with the CASE clause
                    userId, 
                    creationDateTime,
                    CASE WHEN userId = '5A5BC717-F33A-42A5-8E48-99531C30EC87' AND isCurrentAssigned = 1
                         THEN CAST (0 AS BIT)
                         ELSE isCurrentAssigned
                    END AS isCurrentAssigned
                FROM OPENJSON(@SomeJSON, '$.assignations')
                WITH(userId UNIQUEIDENTIFIER, creationDateTime DATETIME, isCurrentAssigned BIT)
    
                UNION ALL -- the insert is done using UNION ALL
    
                SELECT '5A5BC717-F33A-42A5-8E48-99531C30EC87' AS userId, '' AS creationDateTime, CAST (1 AS BIT) AS isCurrentAssigned 
    
            ) Result
            FOR JSON PATH
        )
    
    
        SET @SomeJSON = JSON_MODIFY(@SomeJSON, '$.assignations', JSON_QUERY(@NewParentAssignations))
    
        SELECT @SomeJSON
    

    最后这会产生相同的结果。

    【讨论】:

      猜你喜欢
      • 2020-07-21
      • 2019-04-01
      • 2021-09-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-10-06
      相关资源
      最近更新 更多