T-SQL LIKE 谓词无法与 XML 转换的 varchar 中的空格匹配

Zep*_*hyr 3 xml sql-server t-sql like string-searching

最近,我尝试通过将XML数据转换为特定模式来搜索特定模式,varchar(max)尽管我知道这不是最佳实践,并且发现它没有按预期工作:-

设置

declare @container table(
    [Response] xml not null
);

declare @xml xml =
'<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://abc.com/xsd" xmlns:ns="http://abc.com" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
   <soapenv:Header>
     <ns:MessageHeader>
       <xsd:ID>ABC</xsd:ID>
       <xsd:Date>2018-12-31T23:59:59</xsd:Date>
     </ns:MessageHeader>
   </soapenv:Header>
   <soapenv:Body>
     <ns:MessageResponse>
       <ns:return>
         <xsd:ResponseList xsi:nil="true" />
       </ns:return>
     </ns:MessageResponse>
   </soapenv:Body>
 </soapenv:Envelope>';

insert into @container values (@xml);
Run Code Online (Sandbox Code Playgroud)

此查询有效

select *
  from @container
 where cast(Response as varchar(max))
  like '%<xsd:ResponseList xsi:nil="true"%';
Run Code Online (Sandbox Code Playgroud)

注意通配符在 XML 节点之前的3 个字符(即结束' />'

但这不是

select *
  from @container
 where cast(Response as varchar(max))
  like '%<xsd:ResponseList xsi:nil="true" %' -- with space
    or cast(Response as varchar(max))
  like '%<xsd:ResponseList xsi:nil="true" />%' -- whole XML node;
Run Code Online (Sandbox Code Playgroud)

我怀疑这可能是由于转义字符造成的,并尝试了其他一些替代方法,但无济于事,如果有人能对此有所了解,不胜感激。

编辑(已回答)

以下查询将基于 Browstone 先生的见解:-

select *
  from @container
 where cast(Response as varchar(max))
  like '%<xsd:ResponseList xsi:nil="true"/>%';
Run Code Online (Sandbox Code Playgroud)

这是我的以下问题@ CodeReview 与 XQuery 表达式:-

T-SQL 验证来自 SOAP 请求的 XML 节点是否包含任何子节点

Wor*_*DBA 8

这是设计使然。

当您使用 XML 数据类型存储文档时,它会被压缩并组织成 Sql Server 可以有效执行操作的结构。它执行此操作的步骤之一是生成InfoSet。当它这样做时,它会删除它认为不需要的任何内容,在您的示例中,空格:

InfoSet 内容可能不是文本 XML 的相同副本,因为不会保留以下信息:无关紧要的空格、属性顺序、命名空间前缀和 XML 声明。

当您选择该字段的全部内容时(例如,当您将其转换为它时,NVARCHAR(MAX)会在返回之前重建 XML 文档。此文档可能与您插入的文档的副本不同。例如,如果您使用了 self - 关闭元素,Sql Server 可能会返回打开和关闭元素。

文档还继续说:

示例:保留 XML 数据的精确副本

例如,假设政府法规要求您保留 XML 文档的精确文本副本。例如,这些可能包括签署的文件、法律文件或股票交易订单。您可能希望将文档存储在 [n]varchar(max) 列中。

因此,如果您想存储文档的精确副本,那么NVARCHAR(MAX)VARCHAR(MAX)是最佳选择。然后,您可以将其转换为 XML 以供稍后查询(尽管这可能代价高昂)。

有关详细信息,请参阅有关XML 数据类型和列 (SQL Server)的文档以及定义 XML 数据的序列化,其中概述了 Sql Server 在将 XML 转换为字符串类型时应用的规则。

  • 很高兴知道这一点,我已经尝试删除自闭合标签之间的空间,一切正常!非常感谢 Brownstone 先生! (2认同)