首页 > 解决方案 > TSQL XQuery 过滤器仅选择包含至少一个字符(或非数字)的节点

问题描述

我有以下 XML。

<XML>   
    <Data>         
        <Outer>
            <Inner>123ABC</Inner>
        </Outer>
        <Outer>
            <Inner>123</Inner>
        </Outer>
        <Outer>
            <Inner>-123</Inner>
        </Outer>
    </Data>
</XML>

我想选择节点的内容<Inner>,但前提是它不是数字。或者换句话说:我只想选择它,如果它包含至少一个字符。所以结果应该只有123ABC.

我的 SQL 代码目前如下所示。

DECLARE @string NVARCHAR(MAX);
DECLARE @xml XML;
SET @string = 
  '<XML><Data><Outer><Inner>123ABC</Inner></Outer><Outer><Inner>-123</Inner></Outer><Outer><Inner>123</Inner></Outer></Data></XML>';
SET @xml = @string;
SELECT @xml;


SELECT h.value('text()[1]', 'nvarchar(max)')
FROM @xml.nodes('XML') AS Statements(nodes)
OUTER APPLY @xml.nodes('Data/Outer/Inner') AS Data(h)

查询选择所有节点,即123ABC-123123。但是,我只想选择123ABC. 为了使它与我的真实示例一起使用,我需要调整以下OUTER APPLY行:

OUTER APPLY @xml.nodes('Data/Outer/Inner') AS Data(h)

我很确定我的目标可以通过应用如下过滤器来实现。

@xml.nodes('Data/Outer/Inner[FILTER]')

但是,我找不到任何有效的方法。

更新:过滤标准可以更详细地说明如下。仅应显示包含至少一个字母的元素。因此也不应显示以下值,例如:-1.5、1.5、-33

标签: sql-servertsqlxpathxquery

解决方案


如果您的 XML 数据实际上是以下内容(请注意XML您的示例中缺少的结束标记):

<XML>
  <Data>
    <Outer>
      <Inner>123ABC</Inner>
    </Outer>
    <Outer>
      <Inner>123</Inner>
    </Outer>
  </Data>
</XML>

然后你可以使用一个LIKE表达式来检查它是否有一个不是数值的字符:

SELECT X.I.value('text()[1]','varchar(6)') AS [Inner]
FROM @xml.nodes('/XML/Data/Outer/Inner') AS X(I)
WHERE X.I.value('text()[1]','varchar(6)') LIKE '%[^0-9]%'

如果您提供的 XML 是正确的,您将无法使用 XQUERY,因为它不是有效的 XML,因为XML节点没有被关闭。

编辑:基于评论的一些猜想(目标仍然有点不清楚),但是,也许:

SELECT X.I.value('text()[1]','varchar(6)') AS [Inner]
FROM @xml.nodes('/XML/Data/Outer/Inner') AS X(I)
WHERE TRY_CONVERT(decimal(38,0),X.I.value('text()[1]','varchar(6)')) IS NULL;

或者,基于此陈述“信中的字符”。, 简单地:

SELECT X.I.value('text()[1]','varchar(6)') AS [Inner]
FROM @xml.nodes('/XML/Data/Outer/Inner') AS X(I)
WHERE X.I.value('text()[1]','varchar(6)') LIKE '%[A-z]%';

推荐阅读