Compare two sets of XML data using XQuery in SQL Server

后端 未结 3 1557
野的像风
野的像风 2021-01-02 08:13

Suppose I store employee data in a xml column in my log table. Sometimes data is also updated in the xml column from a stored procedure.

He

相关标签:
3条回答
  • 2021-01-02 08:51

    I am too late here !!! However I found that if employees XML as shown above has multiple records then the JOIN query with CTE returns incorrect results.

    I have below XML input

    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>'
    

    I will use below query to find the difference

    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)
    

    Hope this helps !!!

    0 讨论(0)
  • 2021-01-02 08:53
    ;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, '')    
    

    Result:

    NodeName             Value1               Value2
    -------------------- -------------------- --------------------
    EmpID                1005                 1006
    DOB                  12/02/1981           05/02/1981
    DeptID               ACC001               ACC002
    Salary               10,500               10,900
    
    0 讨论(0)
  • 2021-01-02 09:00

    I don't have the exact output you wanted - but at least you get a good comparison of old and new values:

    ;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
    

    Gives you an output of:

                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 is great for storing and manipulating data - but presentation like this should be done in a front-end application (like an ASP.NET application) - not in T-SQL....

    0 讨论(0)
提交回复
热议问题