假设我将员工数据存储在我的日志表的xml
列中。有时,数据也会在存储过程的xml
列中更新。
以下是示例示例
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>'
我需要显示的两个xml
数据存在一些差异,如旧值&amp;新值作为sql的输出
Old Value New Value
--------- ---------
1005 1006
12/02/1981 05/02/1981
ACC001 ACC002
10,500 10,900
我只需要像上面那样展示差异。因此,请指导我如何使用XQuery比较两个xml数据,并仅在SQL Server中以上述方式显示差异。请引导我使用代码段。感谢
答案 0 :(得分: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, '')
结果:
NodeName Value1 Value2
-------------------- -------------------- --------------------
EmpID 1005 1006
DOB 12/02/1981 05/02/1981
DeptID ACC001 ACC002
Salary 10,500 10,900
答案 1 :(得分:2)
我没有您想要的完全输出 - 但至少您可以很好地比较旧值和新值:
;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中...
答案 2 :(得分:1)
我来不及!!!但是我发现,如果上面显示的员工XML有多条记录,那么带有CTE的JOIN查询会返回不正确的结果。
我有以下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)
希望这有帮助!!!