从两个XML列中选择和匹配值

时间:2018-11-27 05:58:42

标签: sql sql-server xml sql-server-2008-r2

我有两个XML。一个代表旧价值,另一个代表新价值。这两个XMl都是表的列。

表A

| ID  | Old Value                        | New Value                        |
+-----+----------------------------------+----------------------------------+
| 1   | <Root>                           | <Root>                           |
|     | <ScreenrightsManagement>         | <ScreenrightsManagement>         |
|     | <SCREENRIGHTID>8</SCREENRIGHTID> | <SCREENRIGHTID>8</SCREENRIGHTID> |
|     | <SCREENID>9</SCREENID>           | <SCREENID>10</SCREENID>          |
|     | <ROLEID>1</ROLEID>               | <ROLEID>2</ROLEID>               |
|     | </ScreenrightsManagement>        | </ScreenrightsManagement>        |
|     | </Root>                          | </Root>                          |

预期输出:

  Table Name                Field Name       Old Value    New Value
  ScreenrightsManagement    SCREENRIGHTID    8            8
  ScreenrightsManagement    SCREENID         9            10
  ScreenrightsManagement    ROLEID           1            2

我需要从XML中选择值并获得预期的输出,如图所示。我该怎么办?

2 个答案:

答案 0 :(得分:4)

下面的查询将帮助您获得结果。

SELECT 
oldvalue.ID
,oldvalue.tablename
,oldvalue.Colname as fieldname
,oldvalue.ColValue as oldvalue
,newvalue.ColValue as newvalue

 FROM
(
SELECT 
    q.ID,
    t.p.value('local-name(.)', 'varchar(50)') as Colname,
    t.p.value('(.)[1]', 'varchar(50)') as ColValue,
    t.p.value('local-name(..)[1]', 'varchar(50)') as tablename
FROM #test q
    CROSS APPLY oldvalue.nodes('/Root/ScreenrightsManagement/*') t(p)
)oldvalue
inner join 
(
SELECT 
    q.ID,
    t.p.value('local-name(.)', 'varchar(50)') as Colname,
    t.p.value('(.)[1]', 'varchar(50)') as ColValue,
    t.p.value('local-name(..)[1]', 'varchar(50)') as tablename
FROM #test q
    CROSS APPLY newvalue.nodes('/Root/ScreenrightsManagement/*') t(p)
)newvalue ON newvalue.Id=oldvalue.Id and newvalue.Colname=oldvalue.Colname
 and newvalue.tablename=oldvalue.tablename

答案 1 :(得分:2)

以下内容将从XML中提取所有名称和值并将它们联接在一起:

SELECT
    t.ID,
    o.nodes.value('local-name(.)', 'VARCHAR(100)') AS nodeName,
    o.nodes.value('.', 'VARCHAR(100)') value1,
    n.nodes.value('.', 'VARCHAR(100)') value2
FROM @tablea AS t
CROSS APPLY t.OldValue.nodes('/Root/ScreenrightsManagement/*') AS o(nodes)
CROSS APPLY t.NewValue.nodes('/Root/ScreenrightsManagement/*') AS n(nodes)
WHERE o.nodes.value('local-name(.)', 'VARCHAR(100)') = n.nodes.value('local-name(.)', 'VARCHAR(100)')

Demo on DB Fiddle