0

我有以下查询来比较两个 xml 变量并找出两者之间的区别:

DECLARE 
      @oldXML NVARCHAR(MAX)
    , @newXML NVARCHAR(MAX)

SELECT 
      @oldXML = '<root><row USER_KEY="1" USER_NAME="test" USER_ID="12345" USER_STATUS=" " USER_GENDER="F" /></root>' 
    , @newXML = '<root><row USER_KEY="1" USER_NAME="test" USER_ID="00000" USER_STATUS=" " USER_GENDER="F" /></root>'

;WITH cte AS 
(
    SELECT id, t.rn, token = SUBSTRING(name, 1, CHARINDEX('" ', t.name) - 1)
    FROM (
        SELECT 
              name = 
                SUBSTRING(
                      t.string
                    , number + 2
                    , ABS(CHARINDEX('="', t.string, number + 1) - number - 1))
            , rn = ROW_NUMBER() OVER (PARTITION BY t.id ORDER BY (SELECT 1))
            , id
        FROM (
            SELECT id = 1, string = @newXML

            UNION ALL

            SELECT id = 2, @oldXML
        ) t
        CROSS JOIN [master].dbo.spt_values n
        WHERE [type] = 'p'
            AND number <= LEN(t.string) - 1
            AND SUBSTRING(t.string, number, 2) = '="'
    ) t
)
SELECT t2.token
FROM (
    SELECT * 
    FROM cte 
    WHERE id = 1
) t1
LEFT JOIN (
    SELECT * 
    FROM cte 
    WHERE id = 2
) t2 ON t1.rn = t2.rn AND t1.token != t2.token
WHERE t2.token IS NOT NULL

这给了我 oldxml 和 newxml 中的不同字段。在上面的示例中,输出是 12345,这是 USER_ID 是唯一不同的字段。但在这里我还需要哪个字段/标签不同的名称。在这种情况下,我还需要获取“USER_ID”作为输出。

谢谢

4

1 回答 1

3

为什么不将 XML 视为实际的 XML。示例如下。比较代码取自此处并进行了修改:

DECLARE 
      @oldXML XML
    , @newXML XML

SELECT 
      @oldXML = '<root><row USER_KEY="1" USER_NAME="test" USER_ID="12345" USER_STATUS=" " USER_GENDER="F" /></root>' 
    , @newXML = '<root><row USER_KEY="1" USER_NAME="test" USER_ID="00000" USER_STATUS=" " USER_GENDER="F" /></root>'

;with XML1 as
(
  select T.N.value('local-name(.)', 'nvarchar(100)') as NodeName,
         T.N.value('.', 'nvarchar(100)') as Value
  from @oldXML.nodes('/root/row/@*') as T(N)
),
XML2 as
(
  select T.N.value('local-name(.)', 'nvarchar(100)') as NodeName,
         T.N.value('.', 'nvarchar(100)') as Value
  from @newXML.nodes('/root/row/@*') as T(N)
)
select coalesce(XML1.NodeName, XML2.NodeName) as NodeName, 
       XML1.Value as Value1, 
       XML2.Value as Value2
from XML1
  full outer join XML2
    on XML1.NodeName = XML2.NodeName
where coalesce(XML1.Value, '') <> coalesce(XML2.Value, '')    

这将返回:

NodeName    Value1  Value2
USER_ID     12345   00000
于 2013-06-13T18:05:08.267 回答