繁体   English   中英

'local-name()' 需要单例(或空序列)T-SQL Xquery

[英]'local-name()' requires a singleton (or empty sequence) T-SQL Xquery

这是这两个问题的变体/组合,但我想我已经按照他们的描述做了:

有没有办法在 SQL Server 2016 T-SQL 查询中获取节点的名称?

我想做这个:

select 
    trcid,
    trcXML.value(
        'local-name(//*[local-name()="after"][1]/*[1])',  
        'varchar(32)'
    ) as XmlTableName,
    trcXml, 
    trcGUID, 
    trcCorrID 
from trace 
order by trcId desc

我在层次结构中的每个项目之后都明确包含了[1]

错误:XQuery [trace.trcXML.value()]: 'local-name()' 需要单例(或空序列),找到类型为'element(*,xdt:untyped) *'

样本数据:

<s1:DB2Request xmlns:s1="XYZDB2">
  <s1:sync>
    <s1:after identityInsert="false">
      <s1:PG204AT5>
        <s1:ISA06>1975111</s1:ISA06>
           etc... 
      </s1:PG204AT5>
    </s1:after>
  </s1:sync>
</s1:DB2Request>

我想要位于“after”和 ISA06 元素之间的表名(这是一个 BizTalk“update-gram”),在本例中为:PG204AT5。

在 xpathtester.com 中测试: local-name(//*[local-name()="after"][1]/* [1]) - 出于某种原因,当我保存它时,XPATH 被更改: http:// www.xpathtester.com/xpath/2bd602d8fc7aee0484de14bf93f71ef2

另一组括号根据需要为您提供单例:

DECLARE @t TABLE(s XML);
INSERT INTO @t(s)VALUES(N'<s1:DB2Request xmlns:s1="XYZDB2">
  <s1:sync>
    <s1:after identityInsert="false">
      <s1:PG204AT5>
        <s1:ISA06>1975111</s1:ISA06>
           <somethingsomething/>
      </s1:PG204AT5>
    </s1:after>
  </s1:sync>
</s1:DB2Request>');

select 
    s.value(
        'local-name((//*[local-name()="after"][1]/*)[1])',  
        'varchar(32)'
    ) as XmlTableName
from @t;

结果是:

XmlTableName
PG204AT5

请记住,与大多数 XQuery 实现不同,SQL Server 引擎执行“悲观静态类型化”——它假设如果事情可能出错,他们就会出错。

表达式//*[local-name()="after"][1]/* [1]能够返回多个元素 - 例如它会使用这个输入返回

<x>
  <y>
    <after>
       <z/>
    </after>
  </y>
  <y>
    <after>
       <z/>
    </after>
  </y>
</x>

因此 XQuery 编译器推断出静态类型的 element()*,这不符合要求。

简单地执行(//*[local-name()="after"]/*)[1]可能就足够了。

就我个人而言,我一直认为悲观的静态类型是一个非常糟糕的设计选择,但包括 Microsoft 在内的一些早期 XQuery 实现者非常热衷于它。

或者通过明确询问<s1:after>元素的第一个子节点名称来更简单的解决方案。

SQL

-- DDL and sample data population, start
DECLARE @tbl TABLE(xmldata XML);
INSERT INTO @tbl(xmldata)
VALUES(N'<s1:DB2Request xmlns:s1="XYZDB2">
  <s1:sync>
    <s1:after identityInsert="false">
      <s1:PG204AT5>
        <s1:ISA06>1975111</s1:ISA06>
           <somethingsomething/>
      </s1:PG204AT5>
    </s1:after>
  </s1:sync>
</s1:DB2Request>');
-- DDL and sample data population, end

;WITH XMLNAMESPACES (DEFAULT 'XYZDB2')
SELECT xmldata.value('local-name((/DB2Request/sync/after/child::node())[1])','VARCHAR(50)') as XmlTableName
FROM @tbl;

输出

+--------------+
| XmlTableName |
+--------------+
| PG204AT5     |
+--------------+

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM