【问题标题】:Parsing nested XML into SQL table将嵌套的 XML 解析为 SQL 表
【发布时间】:2011-12-24 03:42:26
【问题描述】:

根据所需布局(如下)将以下 XML 块解析为 SQL Server 表的正确方法是什么?是否可以使用单个 SELECT 语句而不使用 UNION 或循环来执行此操作?有接盘侠吗?提前致谢。 输入 XML:

<ObjectData>
  <Parameter1>some value</Parameter1>
  <Parameter2>other value</Parameter2>
  <Dates>
    <dateTime>2011-02-01T00:00:00</dateTime>
    <dateTime>2011-03-01T00:00:00</dateTime>
    <dateTime>2011-04-01T00:00:00</dateTime>
  </Dates>
  <Values>
    <double>0.019974</double>
    <double>0.005395</double>
    <double>0.004854</double>
  </Values>
  <Description>
    <string>this is row 1</string>
    <string>this is row 2</string>
    <string>this is row 3</string>
  </Values>
</ObjectData>

所需的表格输出:

Parameter1  Parameter2      Dates               Values      Description

Some value  Other value 2011-02-01 00:00:00.0   0.019974    this is row 1
Some value  Other value 2011-03-01 00:00:00.0   0.005395    this is row 2
Some value  Other value 2011-04-01 00:00:00.0   0.004854    this is row 3

我正在使用 OPENXML 或 xml.nodes() 功能执行 SELECT SQL 语句。例如,下面的 SELECT 语句导致值和日期之间产生(即值和日期的所有排列),这是我想要避免的。

SELECT 
doc.col.value('Parameter1[1]', 'varchar(20)') Parameter1, 
doc.col.value('Parameter2[1]', 'varchar(20)') Parameter2, 
doc1.col.value('.', 'datetime') Dates ,
doc2.col.value('.', 'float') [Values] 
FROM 
@xml.nodes('/ObjectData') doc(col),
@xml.nodes('/ObjectData/Dates/dateTime') doc1(col),
@xml.nodes('/ObjectData/Values/double') doc2(col);

【问题讨论】:

    标签: sql sql-server xml xml-parsing


    【解决方案1】:

    您可以使用数字表从子元素中选择第一、第二、第三行等。在这个查询中,如果提供了日期,我将返回的行数限制为数字。如果值或描述多于日期,则必须修改联接以将其考虑在内。

    declare @XML xml = '
    <ObjectData>
      <Parameter1>some value</Parameter1>
      <Parameter2>other value</Parameter2>
      <Dates>
        <dateTime>2011-02-01T00:00:00</dateTime>
        <dateTime>2011-03-01T00:00:00</dateTime>
        <dateTime>2011-04-01T00:00:00</dateTime>
      </Dates>
      <Values>
        <double>0.019974</double>
        <double>0.005395</double>
        <double>0.004854</double>
      </Values>
      <Description>
        <string>this is row 1</string>
        <string>this is row 2</string>
        <string>this is row 3</string>
      </Description>
    </ObjectData>'
    
    ;with Numbers as
    (
      select number
      from master..spt_values
      where type = 'P'
    )
    select T.N.value('Parameter1[1]', 'varchar(50)') as Parameter1,
           T.N.value('Parameter2[1]', 'varchar(50)') as Parameter2,
           T.N.value('(Dates/dateTime[position()=sql:column("N.Number")])[1]', 'datetime') as Dates,
           T.N.value('(Values/double[position()=sql:column("N.Number")])[1]', 'float') as [Values],
           T.N.value('(Description/string[position()=sql:column("N.Number")])[1]', 'varchar(max)') as [Description]
    from @XML.nodes('/ObjectData') as T(N)
      cross join Numbers as N
    where N.number between 1 and (T.N.value('count(Dates/dateTime)', 'int'))
    

    【讨论】:

    • 非常感谢你,米凯尔。它确实运作良好!语法仍然令人难以置信,我想它会更简单一些...... :)
    【解决方案2】:

    使用OPENXML 函数。它是一个行集提供程序(它返回从 XML 解析的行集),因此可以在 SELECT 或 INSERT 中使用,例如:

    INSERT INTO table SELECT * FROM OPENXML(source, rowpattern, flags)
    

    为清楚起见,请参阅文档链接中的第一个示例。

    【讨论】:

      【解决方案3】:

      通常,如果您想解析 XML,您会使用像 Perl、Python、Java 或 C# 这样的编程语言,a) 具有 XML DOM,并且 b) 可以与关系数据库通信。

      这是一篇简短的文章,向您展示了在 C# 中读写 XML 的一些基础知识......甚至还有一个如何从 SQL 查询创建 XML 文档的示例(一行!):

      http://www.c-sharpcorner.com/uploadfile/mahesh/readwritexmltutmellli2111282005041517am/readwritexmltutmellli21.aspx

      【讨论】:

      • 谢谢,但这不是我要找的。我在使用 OPENXML 或 xml.nodes() 功能的 SQL 语句之后。以下 select 语句导致值和日期之间产生,这是我想避免的。 SELECT doc.col.value('Parameter1[1]', 'varchar(20)') Parameter1, doc.col.value('Parameter2[1]', 'varchar(20)') Parameter2, doc1.col.value ('.', 'datetime') 日期 ,doc2.col.value('.[1]', 'float') [Values] FROM @xml.nodes('/ObjectData') doc(col) ,@xml.节点('/ObjectData/Dates/dateTime') doc1(col) ,@xml.nodes('/ObjectData/Values/double') doc2(col);
      猜你喜欢
      • 1970-01-01
      • 2020-02-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-08-20
      • 1970-01-01
      • 2011-09-24
      • 2020-10-01
      相关资源
      最近更新 更多