【问题标题】:Updating a column with JSON data in another table使用另一个表中的 JSON 数据更新列
【发布时间】:2018-12-04 10:28:17
【问题描述】:

我在 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"}}]  |     
+-------+----------------------------------------------------------------+

现在的想法是将约翰的名字改为杰夫。

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

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

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

【问题讨论】:

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

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


【解决方案1】:

您可以使用openjson 和带有with 子句的双cross apply 来读取您的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

更新前:

更新后:

【讨论】:

    【解决方案2】:

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

    两点:我说得对吗,你把新旧价值观混为一谈了?我是不是 正确,以上只是一个示例,您正在寻找一个 通用解决方案,其中更新可能会影响不同的列, 甚至每行不止一个?至少 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
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-12-27
      • 1970-01-01
      • 2012-04-07
      • 1970-01-01
      相关资源
      最近更新 更多