【问题标题】:xml to tsql select statement returns only one rowxml to tsql select 语句只返回一行
【发布时间】:2017-10-23 10:51:14
【问题描述】:

我需要使用 xml 构建一个表。

这是我的 xml:

<root>
  <Child>c1</Child>
  <Child>c2</Child>
  <Child>c3</Child>
  <Child>c4</Child>
  <ID>9908</ID>
</root>

我的尝试:

DECLARE @ixml INT,
@Param  VARCHAR(max)='<root>
  <Child>c1</Child>
  <Child>c2</Child>
  <Child>c3</Child>
  <Child>c4</Child>
  <ID>9908</ID>
</root>'


 EXEC sp_xml_preparedocument  @ixml OUTPUT, @Param  

    Select Child,ID
    FROM OPENXML(@ixml, 'root')
    WITH 
    (
        Child [nVARCHAR](max) 'Child',  
        ID [INT] 'ID'
    ) 


----------

实际输出:

Child  |    ID
c1     |    9908

预期输出:

Child  |    ID
c1     |    9908
c2     |    9908
c3     |    9908
c4     |    9908

谁能帮帮我?

【问题讨论】:

  • 我建议您尝试只选择Child 元素,然后在您拥有该权利后添加ID
  • FROM OPENXML 与相应的 SP 准备和删除文档已过时,不应再使用。而是使用适当的methods the XML data type provides

标签: sql sql-server xml tsql


【解决方案1】:

试试这个:

DECLARE @ixml INT,
@Param  VARCHAR(max)='<root>
  <Child>c1</Child>
  <Child>c2</Child>
  <Child>c3</Child>
  <Child>c4</Child>
  <ID>9908</ID>
</root>'


 EXEC sp_xml_preparedocument  @ixml OUTPUT, @Param  

Select Child, ID
FROM OPENXML(@ixml, '/root/Child')
WITH 
(
    Child [nVARCHAR](max) '.', ID [int]   '../ID'
) 

【讨论】:

  • 太棒了。但是,请记住,您应该在完成后删除 xml 引用 (exec sp_xml_removedocument @ixml;)
  • 由于使用这些存储过程的方式很麻烦(包括忘记关闭文档等的可能性),您应该避开这些,而是​​使用新的 XML 处理方式,如我的回答。
【解决方案2】:

首先将@Param 声明为XML 类型,然后在nodesvalue 中使用XPath 表达式,您会得到:

DECLARE @Param XML='<root>
  <Child>c1</Child>
  <Child>c2</Child>
  <Child>c3</Child>
  <Child>c4</Child>
  <ID>9908</ID>
</root>'

SELECT
    Child=n.v.value('.[1]','NVARCHAR(128)'),
    ID=n.v.value('../ID[1]','INT')
FROM
    @Param.nodes('root/Child') AS n(v);

与预期的结果。


稍微好一点的版本(输入来自@Shnugo),直接选择/root/ID 而不是在XPath 表达式中向后导航:

SELECT
    Child=n.v.value('.[1]','NVARCHAR(128)'),
    ID=@Param.value('(/root/ID/text())[1]','INT')
FROM
    @Param.nodes('root/Child') AS n(v);

【讨论】:

  • 好答案,加分...对于性能,您可能要记住,向后导航是一个缺点,获取text() 比简单的ID[1] 稍快。我会使用SELECT ID=@Param.value('(/root/ID/text())[1]','int'), Child=n.v.value('text()[1]','nvarchar(128)') FROM ...
  • @Shnugo 谢谢你的提示,在我的回答中起作用了。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-03-11
  • 1970-01-01
  • 2015-05-28
  • 1970-01-01
  • 2011-04-20
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多