2012-01-06 13 views
8

में XQuery का उपयोग कर XML डेटा के दो सेटों की तुलना करें मान लीजिए कि मैं अपने लॉग तालिका में xml कॉलम में कर्मचारी डेटा संग्रहीत करता हूं। कभी-कभी संग्रहीत प्रक्रिया से xml कॉलम में डेटा भी अपडेट किया जाता है।SQL सर्वर

यहाँ नमूना उदाहरण

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 डेटा जो मैं एसक्यूएल का एक आउटपुट के रूप में पुराने मूल्य की तरह & नया मान को दिखाने के लिए

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

मैं सिर्फ जरूरत में कुछ अंतर है ऊपर की तरह अंतर दिखाने की जरूरत है। तो कृपया मुझे मार्गदर्शन करें कि XQuery का उपयोग करके दो एक्सएमएल डेटा की तुलना कैसे करें और केवल SQL सर्वर में उपरोक्त फ़ैशन में अंतर दिखाएं। कृपया मुझे कोड स्निपेट के साथ मार्गदर्शन करें। धन्यवाद

उत्तर

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 
+0

यह बहुत अच्छा था .... धन्यवाद – Thomas

+1

+1 उत्कृष्ट काम - मैंने इस बारे में अध्ययन किया कि इसे कैसे प्राप्त किया जाए और पेड़ों के लिए जंगल नहीं देखा! –

+0

डेटा को दिखाने के लिए यूआर कोड में क्या बदलाव करना है, यह दिखाने के लिए कि marc_s डेटा कैसे दिखा रहा है लेकिन मैं marc_s जैसे फ़ील्ड नाम को हार्ड कोड नहीं करना चाहता हूं। क्या आप मदद कर सकते हैं। धन्यवाद – Thomas

2

मैं सटीक उत्पादन आप चाहते थे नहीं है - लेकिन कम से कम आप पुराने और नए मूल्यों का एक अच्छा तुलना मिलती है:

  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 
:

;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 

आप का उत्पादन देता है

एसक्यूएल सर्वर भंडारण और डेटा में हेरफेर करने के लिए बहुत अच्छा है - लेकिन इस तरह की प्रस्तुति फ्रंट-एंड एप्लिकेशन (जैसे एएसपी.नेट आवेदन) में की जानी चाहिए - टी-एसक्यूएल में नहीं ....

+0

आपका प्रयास अच्छा था, लेकिन आप उस क्षेत्र के नाम को कड़ी मेहनत करते हैं जिसे मैं नहीं चाहता हूं। धन्यवाद – Thomas

0

मैं बहुत देर हो चुकी यहाँ हूँ !!! हालांकि मुझे पता चला कि यदि उपरोक्त दिखाए गए कर्मचारी एक्सएमएल में कई रिकॉर्ड हैं तो सीटीई के साथ जॉइन क्वेरी गलत परिणाम देता है।

मैं एक्सएमएल इनपुट नीचे है

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) 

आशा इस मदद करता है खोजने के लिए क्वेरी के नीचे का उपयोग करेगा !!!