Сравнение двух наборов XML-данных с помощью XQuery в SQL Server

предположим, я храню данные о сотрудниках в A xml столбец в моей таблице журнала. Иногда данные также обновляются в

3 ответов


;with XML1 as
(
  select T.N.value('local-name(.)', 'nvarchar(100)') as NodeName,
         T.N.value('.', 'nvarchar(100)') as Value
  from @XML1.nodes('/NewDataSet/Employee/*') as T(N)
),
XML2 as
(
  select T.N.value('local-name(.)', 'nvarchar(100)') as NodeName,
         T.N.value('.', 'nvarchar(100)') as Value
  from @XML2.nodes('/NewDataSet/Employee/*') 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
-------------------- -------------------- --------------------
EmpID                1005                 1006
DOB                  12/02/1981           05/02/1981
DeptID               ACC001               ACC002
Salary               10,500               10,900

у меня нет точно вывод, который вы хотели - но, по крайней мере, вы получаете хорошее сравнение старых и новых значений:

;WITH OldData AS
(
SELECT 
    @XML1.value('(/NewDataSet/Employee/EmpID)[1]', 'int') AS 'EmpID',
    @XML1.value('(/NewDataSet/Employee/Name)[1]', 'varchar(50)') AS 'Name',
    @XML1.value('(/NewDataSet/Employee/DOB)[1]', 'datetime') AS 'DOB',
    @XML1.value('(/NewDataSet/Employee/DeptID)[1]', 'varchar(50)') AS 'DeptID',
    @XML1.value('(/NewDataSet/Employee/Salary)[1]', 'varchar(25)') AS 'Salary'
),
NewData AS
(
SELECT 
    @XML2.value('(/NewDataSet/Employee/EmpID)[1]', 'int') AS 'EmpID',
    @XML2.value('(/NewDataSet/Employee/Name)[1]', 'varchar(50)') AS 'Name',
    @XML2.value('(/NewDataSet/Employee/DOB)[1]', 'datetime') AS 'DOB',
    @XML2.value('(/NewDataSet/Employee/DeptID)[1]', 'varchar(50)') AS 'DeptID',
    @XML2.value('(/NewDataSet/Employee/Salary)[1]', 'varchar(25)') AS 'Salary'
)
SELECT
    'Old values', od.*
FROM OldData od
UNION
SELECT 'New values', nd.*
FROM NewData nd

дает вам выход:

            EmpID  Name   DOB                       DeptID   Salary
Old values  1005   keith  1981-12-02 00:00:00.000   ACC001   10,500
New values  1006   keith  1981-05-02 00:00:00.000   ACC002   10,900

SQL Server отлично подходит для хранение и манипулирование данными - но такая презентация должна выполняться в интерфейсном приложении (например, ASP.NET приложение) - не в T-SQL....


Я слишком поздно здесь !!! Однако я обнаружил, что если employees XML, как показано выше, имеет несколько записей, то запрос JOIN с CTE возвращает неправильные результаты.

у меня ниже ввода XML

DECLARE @XML1 XML
DECLARE @XML2 XML

SET @XML1 = 
'<NewDataSet> 
<Employees>
    <Employee>
        <Name> keith </Name>
        <EmpID> 1005 </EmpID>
        <DOB>12/02/1981</DOB>
        <DeptID>ACC001</DeptID>
        <Salary>10,500</Salary>
    </Employee>
    <Employee>
        <Name> keith </Name>
        <EmpID> 1004 </EmpID>
        <DOB>12/02/1981</DOB>
        <DeptID>ACC001</DeptID>
        <Salary>10,500</Salary>
    </Employee>
</Employees>
</NewDataSet>'

    SET @XML2 = 
    '<NewDataSet> 
    <Employees>
        <Employee>
            <Name> keith </Name>
            <EmpID> 1005 </EmpID>
            <DOB>12/02/1981</DOB>
            <DeptID>ACC001</DeptID>
            <Salary>10,500</Salary>
        </Employee>
        <Employee>
            <Name> keith </Name>
            <EmpID> 1004 </EmpID>
            <DOB>12/02/1981</DOB>
            <DeptID>ACC001</DeptID>
            <Salary>10,501</Salary>
        </Employee>
        <Employee>
            <Name> keith1 </Name>
            <EmpID> 10040 </EmpID>
            <DOB>12/02/1981</DOB>
            <DeptID>ACC001</DeptID>
            <Salary>10,501</Salary>
        </Employee>
    </Employees>
    </NewDataSet>'

Я использую ниже запрос, чтобы найти разницу

select  T.N.value('local-name(.)', 'nvarchar(100)') as NodeName,
T.N.value('.', 'nvarchar(100)') as Value
from @XML2.nodes('/NewDataSet/Employees/Employee/*') as T(N)

EXCEPT

select  T.N.value('local-name(.)', 'nvarchar(100)') as NodeName,
T.N.value('.', 'nvarchar(100)') as Value
from @XML1.nodes('/NewDataSet/Employees/Employee/*') as T(N)

надеюсь, что это помогает !!!