将嵌套的json数组插入sql server中的多个表中

2024-04-23

我在 Sql 服务器中有以下 Json 对象。我想将此数据插入多个表及其关系(即外键):

DECLARE @JsonObject NVARCHAR(MAX) = N'{  
   "FirstElement":{  
      "Name":"ABC",
      "Location":"East US",
      "Region":"West US",
      "InnerElement":[
         {  
            "Name":"IE1",
            "Description":"IE1 Description",
            "Type":"Small",
            "InnerMostElement":[  
               {
                  "Key":"Name",
                  "Value":"IME1"
               },
                {
                  "Key":"AnotherProperty",
                  "Value":"Value1"
               }
            ]
         },
         {  
            "Name":"IE2",
            "Description":"IE2 Description",
            "Type":"Medium",
            "InnerMostElement":[ 
               {
                  "Key":"Name",
                  "Value":"IME2"
               },
                {
                  "Key":"Address",
                  "Value":"Xyz"
               }, 
               {
                  "Key":"Type",
                  "Value":"Simple"
               },
                {
                  "Key":"LastProperty",
                  "Value":"ValueX"
               }
            ]
         }
      ]
   }
}'

表结构附在这里:

我想插入第一元素数据输入Table1, 内部元素数据输入Table2 and 最里面的元素数据输入Table3.


最简单的部分是第一个表,因为我们只插入一行并且它没有依赖项:

BEGIN TRANSACTION;

INSERT Table1([Name], [Location], [Region])
SELECT [Name], [Location], [Region]
FROM OPENJSON(@JsonObject, '$.FirstElement')
WITH (
    [Name] VARCHAR(100),
    [Location] VARCHAR(100),
    [Region] VARCHAR(100)
);

DECLARE @Table1Id INT = SCOPE_IDENTITY();

困难的部分是下一张桌子。我们需要捕获已插入行的所有标识,以及尚未插入到表 3 中的所有数据。因为OUTPUT的条款INSERT仅限于输出基表中的值,我们需要使用MERGE诡计:

DECLARE @Table3Input TABLE([Table2Id] INT, [InnerMostElement] NVARCHAR(MAX));

MERGE Table2
USING (
    SELECT [Name], [Description], [Type], [InnerMostElement]
    FROM OPENJSON(@JsonObject, '$.FirstElement.InnerElement')
    WITH (
        [Name] VARCHAR(100),
        [Description] VARCHAR(100),
        [Type] VARCHAR(100),
        [InnerMostElement] NVARCHAR(MAX) AS JSON
    )
) AS J
ON 1 = 0    -- Always INSERT
WHEN NOT MATCHED THEN 
    INSERT([Table1Id], [Name], [Description], [Type])
    VALUES (@Table1Id, J.[Name], J.[Description], J.[Type])
    OUTPUT inserted.Id, J.[InnerMostElement]
    INTO @Table3Input([Table2Id], [InnerMostElement]);

如果主要使用 JSON 来填充表格,那么使用可能会更方便SEQUENCE对象生成连续值(使用sp_sequence_get_range),无需将整个 JSON 捕获到临时表中。这将大大简化这一过程并消除对MERGE.

最后一张表又很简单:

INSERT Table3([Table2Id], [Key], [Value])
SELECT [Table2Id], KV.[Key], KV.[Value]
FROM @Table3Input CROSS APPLY (
    SELECT [Key], [Value]
    FROM OPENJSON([InnerMostElement])
    WITH (
        [Key] VARCHAR(100),
        [Value] VARCHAR(100)
    )
) AS KV;

COMMIT;

该事务在逻辑上是必要的,以确保该对象被完全插入或根本不插入。

最终输出:

+----+------+----------+---------+
| Id | Name | Location | Region  |
+----+------+----------+---------+
|  1 | ABC  | East US  | West US |
+----+------+----------+---------+
+----+----------+------+-----------------+--------+
| Id | Table1Id | Name |   Description   |  Type  |
+----+----------+------+-----------------+--------+
|  1 |        1 | IE1  | IE1 Description | Small  |
|  2 |        1 | IE2  | IE2 Description | Medium |
+----+----------+------+-----------------+--------+
+----+----------+-----------------+--------+
| Id | Table2Id |       Key       | Value  |
+----+----------+-----------------+--------+
|  1 |        1 | Name            | IME1   |
|  2 |        1 | AnotherProperty | Value1 |
|  3 |        2 | Name            | IME2   |
|  4 |        2 | Address         | Xyz    |
|  5 |        2 | Type            | Simple |
|  6 |        2 | LastProperty    | ValueX |
+----+----------+-----------------+--------+

为了完整起见,将其转换回 JSON 的方法如下:

SELECT 
  [Name] AS 'FirstElement.Name', 
  [Location] AS 'FirstElement.Location', 
  [Region] AS 'FirstElement.Region',
  (
    SELECT 
      [Name], 
      [Description], 
      [Type],
      (
        SELECT 
          [Key], 
          [Value]
        FROM Table3
        WHERE Table3.Table2Id = Table2.Id
        FOR JSON PATH
      ) AS 'InnerMostElement'
    FROM Table2
    WHERE Table2.Table1Id = Table1.Id
    FOR JSON PATH
  ) AS 'FirstElement.InnerElement'
FROM Table1
FOR JSON PATH;
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

将嵌套的json数组插入sql server中的多个表中 的相关文章

随机推荐

  • 正则表达式时区

    我需要一个有效时区的正则表达式 尝试了以下一个 但我不确定 请帮我找出以下正则表达式中的错误 Edited 这里冒号和分钟是可选的 我怎样才能将其更改为强制 如果没有分钟 用户应输入 00 05 00 请帮我解决这个问题 var chkzo
  • 如何将 Git 补丁应用到具有不同名称和路径的文件?

    我有两个存储库 其中 我对文件进行了更改 hello test 我提交更改并从该提交创建补丁git format patch 1 HEAD 现在 我有第二个存储库 其中包含一个与 hello test 内容相同的文件 但以不同的名称放置在不
  • 具有颜色渐变的 3D 散点图,其中颜色取决于计数

    我有一个包含点的数据框 其中包括点的 x y 和 z 坐标以及 计数 每个数据点的数字在 1 到 187 之间 我想将 计数 与颜色渐变相关联 例如1是绿色 187是红色 然后用x y和z坐标绘制数据点的散点图 其中每个数据点的颜色都被编码
  • ECMAScript 规范是否允许 Array 成为“超类”?

    我正在寻找任何迹象表明 超类化 内置类型是否有效根据规格 也就是说 给定任何假设的 ECMAScript 一致实现 超类化 内置函数是否会通过影响类构造函数的创建算法来破坏运行时 超一流 我创造的一个术语 指的是一个类 其通过构造它或将其作
  • Cookie 未设置或首次不起作用

    在每个页面上 我都设置了一个 cookie 来为与该会话对应的标题按钮着色 问题是 当我第一次在不同的部分打开页面时 cookie 仍然是旧的 彩色按钮也是如此 然后 如果我再次单击同一按钮 则 cookie 会被正确设置 为什么 这是我的
  • 为什么苹果设备在自己的播放器中播放html5视频?

    我尝试了不同的 html 播放器并使用 html5 视频标签 然而 苹果设备 ipod touch 4 iphone 4 ipad 在其中显示 html5 视频自己的球员 我的主要目标是在视频上显示叠加广告 我决定借助绝对定位和 z ind
  • iOS4:如何使用视频文件作为 OpenGL 纹理?

    我正在尝试将视频文件的内容 暂时不包含音频 显示到 OpenGL 中的 UV 映射 3D 对象上 我已经在 OpenGL 中做了相当多的工作 但不知道从哪里开始处理视频文件 而且大多数示例似乎都是从相机获取视频帧 这不是我想要的 目前我觉得
  • 列表切片的迭代

    我想要一个算法来迭代列表切片 切片大小在函数外部设置并且可以不同 在我看来 它是这样的 for list of x items in fatherList foo list of x items 有没有办法正确定义list of x ite
  • 如何使 raiserror 和 nowait 与 sqlcmd 一起使用?

    这是命令行 sqlcmd S localhost U myuser P mypwd b r0 Q raiserror hello 10 1 with nowait waitfor delay 00 00 10 raiserror world
  • 无法使用 PayPal 模块处理交易

    我正在尝试测试 Python 和 Paypal 集成 这是我对 PayPal 模块的调用 http www chickenwingsw com paypal on python http www chickenwingsw com payp
  • 根据列的值从其他列获取值

    对于数据框中的每一行 我想根据第三列中的值将值从一列复制到另一列 我尝试使用组合的 for 循环和 if 函数来做到这一点 example condition lt c 1 2 2 1 2 3 3 SZ01 lt c 1 1 1 1 1 1
  • Web 服务资源管理器错误 500

    使用最新版本的 eclipse Luna java ee 下载 启动 Web Services Explorer 时收到 HTTP ERROR 500 控制台中没有消息 故障 防火墙 Windows 和 AV 已关闭 有什么建议么 我通过更
  • 除非调整浏览器窗口大小,否则 Angular ui 网格不会显示内容

    我正在使用 angularjs 1 5 0 和 Angular ui grid 3 1 1 当我在控制器主体中分配 gridOptions 传递给网格指令 对象时 如下所示 scope gridOptions data mock2 1 mo
  • 网站底部的空白区域

    我正在尝试消除我即将推出的投资组合网站底部的空白区域 http codymiracle com http codymiracle com 发生的情况是 在大多数显示器上 页脚似乎太长或太短 要么我在非常小的窗口上滚动 要么更常见的是较大的分
  • 如何在 python 中将浮点数格式化为字符串?

    def main M float input Please enter sales for Monday T float input Please enter sales for Tuesday W float input Please e
  • 编译时引用.NET dll(使用单声道)

    我问了一个安装 F powerpack 并使用它的问题here https stackoverflow com questions 6206406 how to install and use f powerpack in mono err
  • 为 Windows 7 构建自定义凭据提供程序

    在查看了为 Windows 7 构建自定义凭据提供程序的代码后 我设法让自己的磁贴显示在登录屏幕上 并且可以作为所需用户登录 但是 我正在尝试实现一个系统 其中事件 范围内的蓝牙设备 触发登录 解锁 而无需单击磁贴 我可以设置它自动填写密码
  • iPhone |从头开始构建新版本的核心数据迁移

    我正在开发应用程序更新 这个版本完全是从头开始构建的 并且具有全新的功能coreData模型架构 我需要写coreData从旧模型迁移 我一直在寻找资源来写作coreData迁移但都需要旧模型文件 由于这个版本是全新的 所以我没有旧的模型架
  • 连接报告服务中字段的不同行值

    我在报告服务中有一份报告 我想连接以逗号分隔的列的所有不同值 并将该值放入文本框中 我知道我可以使用答案之一在 SQL 中做到这一点here https stackoverflow com questions 4670920 how to
  • 将嵌套的json数组插入sql server中的多个表中

    我在 Sql 服务器中有以下 Json 对象 我想将此数据插入多个表及其关系 即外键 DECLARE JsonObject NVARCHAR MAX N FirstElement Name ABC Location East US Regi