【问题标题】:find the field name when compare two xml variables in sql?比较sql中的两个xml变量时找到字段名称?
【发布时间】:2013-06-14 02:05:08
【问题描述】:

我有以下查询来比较两个 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”作为输出。

谢谢

【问题讨论】:

    标签: sql-server


    【解决方案1】:

    为什么不将 XML 视为实际的 XML。示例如下。对比码为taken from here and modified:

    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
    

    【讨论】:

      猜你喜欢
      • 2015-11-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多