在另一个表中更新带有JSON数据的列

时间:2018-12-04 10:28:18

标签: sql json sql-server tsql sql-update

我在JSON和SQL Server上看过很多东西,但是找不到我想要的东西。

我想通过从另一个表中检索JSON值来更新一个表中的列。

让我们说一下下表:

表格:人

+-------+-----------+
|   id  |   name    |  
+-------+-----------+
|   1   |   John    |      
|   2   |   Mary    |     
|   3   |   Jeff    |       
|   4   |   Bill    |       
|   5   |   Bob     |   
+-------+-----------+

并假装我有另一个表,其中填充了JSON行,如下所示:

表:存档

+-------+----------------------------------------------------------------+
|   id  |   json                                                         |  
+-------+----------------------------------------------------------------+
|   1   |[{ "Column":"name","values": { "old": "Jeff", "new": "John"}}]  |      
|   2   |[{ "Column":"name","values": { "old": "Rose", "new": "Mary"}}]  |     
+-------+----------------------------------------------------------------+

现在的想法是将Johns的名字改成Jeff。

UPDATE people
SET name = JSON_QUERY(archive.json, '$values.old')
WHERE ID = 1

上面的SQL可能没有任何意义,但我只是想了解我目前正在尝试做的事情的逻辑。我希望这有道理。

如果需要更多信息,请询问。

2 个答案:

答案 0 :(得分:1)

您可以使用openjson和带有cross apply的双with来读取json。然后,您可以使用update from来更改@people中的值:

declare @people table (id int, [name] varchar(50))

insert into @people values
 (1, 'John')    
,(2, 'Mary')   
,(3, 'Jeff')     
,(4, 'Bill')     
,(5, 'Bob' )

declare @json table  (id int, [json] nvarchar(max))
insert into @json values
 (1,'[{ "Column":"name","values": { "old": "Jeff", "new": "John"}}]')     
,(2,'[{ "Column":"name","values": { "old": "Rose", "new": "Mary"}}]')    

update @people
set [name] = d.old
from @people p
inner join 
(
     select id
          , c.old
          , c.new
     from @json a
     cross apply openjson(json) with 
     (
         [Column] nvarchar(50)
       , [values] nvarchar(MAX) as JSON
     ) b
     cross apply openjson(b.[values]) with 
     (
         old nvarchar(50)
       , new nvarchar(50)
     ) c
) d 
on p.id = d.id

更新前:

enter image description here

更新后:

enter image description here

答案 1 :(得分:1)

我在上面的评论中问了你一些问题

  

两句话:我是对的,您混合了旧值和新值?我呢   正确,以上只是示例,您正在寻找   通用解决方案,其中更新可能会影响不同的列,   也许每行超过一个?至少JSON将允许更多   对象数组中的元素。

但是-首先-您可以尝试以下操作:

-模拟您的设置(感谢@Andrea,我用了您的)

declare @people table (id int, [name] varchar(50))

insert into @people values
 (1, 'John')    
,(2, 'Mary')   
,(3, 'Jeff')     
,(4, 'Bill')     
,(5, 'Bob' )

declare @json table  (id int, [json] nvarchar(max))
insert into @json values
 (1,'[{ "Column":"name","values": { "old": "Jeff", "new": "John"}}]')     
,(2,'[{ "Column":"name","values": { "old": "Rose", "new": "Mary"}}]')

-至少会返回您需要的一切。其余的大概是动态语句的构建和EXEC()

SELECT p.*
      ,A.[Column]
      ,JSON_VALUE(A.[values],'$.old') AS OldValue
      ,JSON_VALUE(A.[values],'$.new') As NewValue
FROM @people p
INNER JOIN @json j ON p.id=j.id
CROSS APPLY OPENJSON(j.[json]) 
WITH([Column] VARCHAR(100), [values] NVARCHAR(MAX) AS JSON) A;

结果(旧的和新的似乎都错了):

id  name    Column  OldValue    NewValue
1   John    name    Jeff        John
2   Mary    name    Rose        Mary