【问题标题】:How to extract the xml child node using sql如何使用sql提取xml子节点
【发布时间】:2022-01-18 18:34:30
【问题描述】:

我的数据库中有数据类型为 xml 的列。

示例值如下所示。

<Responses>
   <Response>
     <task></task>
   </Response>
  <Response>
     <task></task>
   </Response>
  <Response>
     <task></task>
   </Response>
</Responses>

因此,我需要从上面的 xml 中提取每个节点,并将其保存为另一个表中的不同行。从上面的示例中将有 3 行。

【问题讨论】:

  • 到目前为止你有什么尝试?
  • 我可以使用 xml 中的 select 命令获取每个节点的值,但我无法提取节点本身。在c#中我已经做到了。我们将获得子节点
  • 提问时,您需要提供minimal reproducible example: (1) DDL 和样本数据填充,即 CREATE 表和 INSERT T-SQL 语句。 (2) 你需要做什么,即逻辑和你的代码尝试在 T-SQL 中实现它。 (3) 期望的输出,基于上述#1 中的样本数据。 (4) 您的 SQL Server 版本 (SELECT @@version;)。全部在问题内,没有图片。
  • 通过一个 api 我会得到一个 xml 响应,我将它作为 xml 插入到一个 db 表中,在那个 xml 响应本身中会有几个响应作为子节点,一旦将这个 xml 插入到表中稍后使用存储过程,我需要读取保存的 xml 并提取其中的每个响应并将其插入另一个表中。在上面的例子中,假设它是我首先插入的 api 的响应。然后我需要读取这个 xml 数据并将该 xml 中的每个子节点作为 xml 提取到不同的表中。 我需要提取这个子节点的 3 个

标签: c# sql xml model-view-controller nodes


【解决方案1】:

您可以使用以下 SQL XQuery 解决方案:

.query 会给你一个完整的 XML 节点,而不是.value,它只给你一个内部值。

SELECT x.task.query('.') task
FROM @tmp t
CROSS APPLY t.XmlData.nodes('Responses/Response/task') x(task);

db<>fiddle

输出:

task
&lt;task&gt;1&lt;/task&gt;
&lt;task&gt;2&lt;/task&gt;
&lt;task&gt;3&lt;/task&gt;

【讨论】:

  • @GoldenLion 它将.nodes Table Valued 函数的结果“应用”到每一行,并且该函数会将节点(与 XQuery 输入匹配的节点)“分解”成单独的行.请参阅文档docs.microsoft.com/en-us/sql/t-sql/xml/….query 函数将返回一个 XML 结果,在这种情况下,我们要求 . 是整个节点
  • 感谢我用它来还原我的 xml 结果
【解决方案2】:

尝试以下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using System.IO;

namespace ConsoleApplication7
{
    class Program
    {
        static void Main(string[] args)
        {
            string xml = @"<Responses>
                               <Response>
                                 <task></task>
                               </Response>
                              <Response>
                                 <task></task>
                               </Response>
                              <Response>
                                 <task></task>
                               </Response>
                            </Responses>";
            StringReader reader = new StringReader(xml);
            DataSet ds = new DataSet();
            ds.ReadXml(reader);
        }
    }
}

【讨论】:

    【解决方案3】:

    尝试使用 xml 列,查询。您需要将字符串列转换为 xml,然后使用查询。见 (SQL Server - returning xml child nodes for xml column)

    declare @tmp as table (ID UNIQUEIDENTIFIER,
    CreatedDate DATETIME,
    XmlData XML)
    
    declare @xml as xml='<Responses>
       <Response>
         <task>1</task>
       </Response>
      <Response>
         <task>2</task>
       </Response>
      <Response>
         <task>3</task>
       </Response>
    </Responses>'
    
    insert into @tmp(CreatedDate,XmlData) values(GetDate(),@xml)
    
    
    select XmlData.query('Responses/Response/task') task from @tmp
    

    输出:

    <task>1</task><task>2</task><task>3</task>
    

    使用xml路径节点和值

    select X.Y.value('(task)[1]','int') task from @tmp t
    cross apply t.XmlData.nodes('Responses/Response') as X(Y)
    

    输出

     task
     1
     2
     3
    

    【讨论】:

    • 略有不同:你的取每个Response 并取出第一个task,我的直接转到task。从理论上讲,如果有多个 task 节点,您将只能从每个 Response 中获得第一个节点,尽管 OP 没有表明这种情况
    • 你说的是 1 吗?为什么我会有这样的结构
    猜你喜欢
    • 2021-09-03
    • 1970-01-01
    • 1970-01-01
    • 2017-09-24
    • 2022-10-13
    • 1970-01-01
    • 2013-09-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多