T-SQL:比较 2 个 XML 并返回具有不同值的节点

Posted

技术标签:

【中文标题】T-SQL:比较 2 个 XML 并返回具有不同值的节点【英文标题】:T-SQL: Compare 2 XML and return nodes with different values 【发布时间】:2018-03-24 14:03:28 【问题描述】:

我有 2 个 xml 变量(@xml1 和 @xml2),我需要比较每个节点中的值并返回一个只包含不同节点的 xml。

也就是说,我有这 2 个 XML 变量:

declare @xml1 xml = N'<row>
  <id>1</id>
  <name>record title</name>
  <description>sample description</description>
</row>'
declare @xml2 xml = N'<row>
  <id>1</id>
  <name>record title</name>
  <description>updated sample description</description>
</row>'

我希望它返回:

SELECT @xml1 = N'<row>
  <description>sample description</description>
</row>', @xml2 = N'<row>
  <description>updated sample description</description>
</row>'

我有以下查询返回我需要的类型,但它的 UNpivoted & 没有 xml 节点等:

SELECT
        NV.NodeName,
        OV.NodeValue OldValue,
        NV.NodeValue NewValue
FROM 
(SELECT T.N.value('local-name(.)', 'nvarchar(100)') NodeName,
                T.N.value('.', 'nvarchar(100)') NodeValue
            FROM @xml1.nodes('/row/*') T(N)) NV
CROSS APPLY (SELECT T.N.value('local-name(.)', 'nvarchar(100)') NodeName,
                T.N.value('.', 'nvarchar(100)') NodeValue
            FROM @xml2.nodes('/row/*') T(N)) OV
WHERE OV.NodeName = NV.NodeName AND OV.NodeValue <> NV.NodeValue

性能是关键:这段代码在触发器中,所以它需要快速运行,我害怕使用 PIVOT,因为它往往很慢。我希望有更好的方法来比较和返回已经作为 xml 值的值。

有什么想法吗? 提前致谢!

【问题讨论】:

【参考方案1】:

没关系 - 想通了 =) 如果这对以后的任何人都有帮助:

声明@XMLString1 VARCHAR(MAX) = '', @XMLString2 VARCHAR(MAX) = '';

SELECT @XMLString1 += '<' + OV.NodeName + '>' + LEFT(OV.NodeValue, 8000) + '</' + OV.NodeName + '>',
       @XMLString2 += '<' + NV.NodeName + '>' + LEFT(NV.NodeValue, 8000) + '</' + NV.NodeName + '>'
FROM 
    (SELECT T.N.value('local-name(.)', 'varchar(255)') NodeName,
            T.N.value('.', 'varchar(8000)') NodeValue
    FROM @xml1.nodes('/row/*') T(N)) NV
CROSS APPLY 
    (SELECT T.N.value('local-name(.)', 'varchar(255)') NodeName,
            T.N.value('.', 'varchar(8000)') NodeValue
    FROM @xml2.nodes('/row/*') T(N)) OV
WHERE OV.NodeName = NV.NodeName AND OV.NodeValue <> NV.NodeValue
SET @XMLString1 = '<row>' + ISNULL(@XMLString1, '') + '</row>';
SET @XMLString2 = '<row>' + ISNULL(@XMLString2, '') + '</row>';

SELECT CONVERT(XML, @XMLString1) xml1, CONVERT(XML, @XMLString2) xml2

【讨论】:

以上是关于T-SQL:比较 2 个 XML 并返回具有不同值的节点的主要内容,如果未能解决你的问题,请参考以下文章

比较两个数组并返回重复值

T-SQL 以表格格式解析 XML 响应

使用 T-SQL 中另一个(非 xml)列的值更新 XML

比较具有不同属性数量的两个数组,并使用javascript在条件下将第三个数组映射到比较值

比较两个字典(键,值)并返回不具有相同值的键

SET ANSI_NULLS ON 在T-SQL中是什么意思