XPath查询:使用相同的查询解析多个路径(Cross Apply / .nodes())

时间:2015-06-19 13:59:05

标签: sql-server xml tsql xpath

我有一个相当大的结构化XML收据,我要将其解析为关系数据库。在不同的级别上有一些相同的结构,因此使用相同的SQL语句解析它们是非常好的。像:

DECLARE @XMLPath varchar(127)
SET @XMLPath = 'atag/btag/item'

INSERT INTO XMLReadItems
  SELECT ci.InvoiceID, 
    T.c.value('productname[1]', 'varchar(63)') AS InvoiceTarget,
    T.c.value('unit[1]', 'varchar(15)') AS Unit,
FROM @XMLItems ci CROSS APPLY XMLCol.nodes(*[local-name()=sql:variable("@XMLPath")]') T(c)

@XMLPath可以是变量的字符串,也可以是表格中的字段(使用sql:column()怎么办?)。但是他们中的任何一个我都无法工作。 我只能在XMLCol.nodes()中使用静态字符串。

1 个答案:

答案 0 :(得分:2)

您无法动态构造XQuery参数,因为它仅限于文字字符串。请参阅MSDN关于nodes() XML方法的参数的说明:

  

的XQuery

     

是字符串文字,XQuery表达式。如果查询表达式构造节点,则这些构造的节点将在结果行集中公开。如果查询表达式导致空序列,则行集将为空。如果查询表达式静态地导致包含原子值而不是节点的序列,则会引发静态错误。

强制将SQL变量传递给nodes()方法会触发错误:

  

XML数据类型方法的参数1"节点"必须是字符串文字。

您尝试实施的技巧仅适用于动态匹配元素,而不是动态构建整个XPath 。例如,以下内容应该可以正常处理item元素:

SET @elementName = 'item'

SELECT .....
FROM @XMLItems ci 
CROSS APPLY XMLCol.nodes('//*[local-name()=sql:variable("@elementName")]') T(c)

最终,除非您想进一步动态构建整个查询,否则我无法解决此限制(请参阅:sp_executesql)。