2012-01-06 41 views
8

Giả sử tôi lưu trữ dữ liệu của nhân viên trong cột xml trong bảng nhật ký của tôi. Đôi khi dữ liệu cũng được cập nhật trong cột xml từ một thủ tục được lưu trữ.So sánh hai bộ dữ liệu XML bằng XQuery trong SQL Server

Dưới đây là ví dụ mẫu

DECLARE @XML1 XML 
DECLARE @XML2 XML 

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

SET @XML2 = 
'<NewDataSet> 
<Employee> 
<EmpID>1006</EmpID> 
<Name> keith </Name> 
<DOB>05/02/1981</DOB> 
<DeptID>ACC002</DeptID> 
<Salary>10,900</Salary> 
</Employee> 
</NewDataSet>' 

Có một số khác biệt trong hai dữ liệu xml mà tôi cần phải chứng minh như giá trị cũ & giá trị mới như một đầu ra của sql

Old Value    New Value 
---------    --------- 
1005     1006 
12/02/1981   05/02/1981 
ACC001    ACC002 
10,500    10,900 

Tôi chỉ cần thể hiện sự khác biệt như trên. Vì vậy, hãy hướng dẫn tôi cách so sánh hai dữ liệu xml bằng cách sử dụng XQuery và hiển thị sự khác biệt chỉ trong thời trang trên trong SQL Server. Vui lòng hướng dẫn tôi bằng đoạn mã. nhờ

Trả lời

15
;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, '')  

Kết quả:

NodeName    Value1    Value2 
-------------------- -------------------- -------------------- 
EmpID    1005     1006 
DOB     12/02/1981   05/02/1981 
DeptID    ACC001    ACC002 
Salary    10,500    10,900 
+0

thật tuyệt vời .... cảm ơn – Thomas

+1

+1 công việc tuyệt vời - Tôi đã tiếp tục nghiên cứu cách để đạt được điều này và không thấy rừng cho cây cối! –

+0

những gì để thay đổi trong mã ur để hiển thị dữ liệu như thế nào marc_s dữ liệu được hiển thị nhưng tôi không muốn mã cứng tên trường như marc_s. bạn có thể plzz giúp đỡ. cảm ơn – Thomas

2

tôi không có đầu ra chính xác bạn muốn - nhưng ít nhất bạn sẽ có được một sự so sánh tốt các giá trị cũ và mới:

;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 

Cung cấp cho bạn một sản lượng:

  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 

Máy chủ SQL rất tốt cho việc lưu trữ và thao tác dữ liệu - nhưng việc trình bày như thế này phải được thực hiện trong ứng dụng đầu cuối (như ứng dụng ASP.NET) - không có trong T-SQL ....

+0

nỗ lực ur là tốt nhưng u mã cứng tên trường mà tôi không muốn. Cảm ơn – Thomas

0

Tôi quá muộn here !!! Tuy nhiên tôi thấy rằng nếu nhân viên XML như được hiển thị ở trên có nhiều bản ghi thì truy vấn JOIN với CTE trả về kết quả không chính xác.

tôi có dưới đây đầu vào 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>' 

tôi sẽ sử dụng dưới đây truy vấn để tìm ra sự khác biệt

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

Các vấn đề liên quan