डायनामिक एसक्यूएल (पिवट क्वेरी) को xml आउटपुट में परिवर्तित करते समय, दिनांक का पहला अंक यूनिकोड में क्यों परिवर्तित किया जाता है?


11

मैं इस महान उदाहरण का उपयोग कर रहा हूँ https://dba.stackexchange.com/a/25818/113298 Bluefeet से, एक धुरी बनाने के लिए और इसे xml डेटा में बदलने के लिए।

परम की घोषणा

DECLARE @cols AS NVARCHAR(MAX),  @query  AS NVARCHAR(MAX);

आगे एक CTE है जिसमें बहुत सारे कोड हैं, CTE का एंडोर्समेंट एक अस्थायी DB में रखा गया है (उदाहरण के रूप में)

SELECT 
B.[StayDate] -- this is a date dd-mm-yyyy
, B.[Guid]
INTO #tempDates
FROM BaseSelection B

कर्नल बनाना (उदाहरण के समान)

SELECT @cols = STUFF((SELECT distinct ',' +QUOTENAME(convert(char(10), [StayDate] , 120)) 
FROM #tempDates
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)') 
,1,1,'');

परिणाम सेट वही है जिसकी मुझे उम्मीद करनी चाहिए

set @query = 
   'SELECT [Guid],' + @cols +'
    FROM
    (
        SELECT 
            [StayDate] 
           ,[Guid]
        FROM #tempDates
    ) A
    pivot
    (
        count([StayDate])
        for [StayDate] in (' + @cols +')                    
    ) p
    '
EXEC sp_executesql  @query ;

यहाँ छवि विवरण दर्ज करें

जब मैं इसे XML में बदलने की कोशिश करता हूं तो मेरी विशेषताएँ आंशिक रूप से परिवर्तित हो जाती हैं

set @query = 
   'SELECT [Guid],' + @cols +'
    FROM
    (
        SELECT 
            [StayDate] 
           ,[Guid]
        FROM #tempDates
    ) A
    pivot
    (
        count([StayDate])
        for [StayDate] in (' + @cols +')                    
    ) p
    for xml auto
    -- when using for XML path i will get a error
    -- FOR XML PATH(''''), ROOT(''root'') 
    -- Msg 6850, Level 16, State 1, Line 3
    -- Column name '2016-12-17' contains an invalid XML identifier 
    -- as required by FOR XML; '2'(0x0032) is the first character at fault.
    '
EXEC sp_executesql  @query ;

परिणाम सेट

<p Guid="3C3359E3-CFE5-E511-80CA-005056A90901"
  _x0032_016-12-17="2" --> should be 2016-12-17="2" 
  _x0032_016-12-18="2" --> should be 2016-12-18="2" 
  _x0032_016-12-19="2" --> should be 2016-12-19="2" 
/>

क्या मैं कुछ याद कर रहा हूं, केवल तारीख का एक हिस्सा यूनिकोड में क्यों बदल गया है?

मैं इसे कैसे ठीक करूं?


SQL सर्वर का कौन सा संस्करण इसके लिए है?
ypercube y

एसक्यूएल सर्वर 2012, लेकिन वह बिंदु नहीं है, यह इस मामले में महत्वपूर्ण है कि एक्सएमएल का चश्मा है
बंकरबस्टर

यह एक XY- समस्या की तरह लगता है। XML में एक विशेषता नाम के रूप में एक तारीख का उपयोग करना बीमार लगता है, भले ही यह उद्देश्य के अनुसार काम किया हो। मैं एक विशेषता के मूल्य के रूप में या शायद एक तत्व के पाठ के रूप में तारीख को संग्रहीत करने के लिए इच्छुक हूं , जो इस पर निर्भर करता है कि मैंने इसके साथ क्या करने की योजना बनाई है। यदि आवश्यक हो, तो मैं विशेषताओं के जोड़े के साथ कई तत्व बनाऊंगा।
jpmc26

जवाबों:


14

XML में विशेषता नाम एक नंबर से शुरू करने की अनुमति नहीं है, NameStartChar देखें ।

आपको अपनी विशेषताओं के लिए वैकल्पिक नामों के साथ आना होगा और @colsअपने डायनामिक पिवट क्वेरी के लिए एक अलग वैरिएबल निर्दिष्ट कॉलम एलियास में एनकोड करना होगा।

SELECT @cols2 = STUFF((SELECT distinct ',' +
                       quotename(convert(char(10), [StayDate] , 120)) + 
                       ' as '+ QUOTENAME('z'+convert(char(10), [StayDate] , 120)) 
FROM #tempDates
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)') 
,1,1,'');

परिणाम;

[2016-12-20] as [z2016-12-20],[2016-12-21] as [z2016-12-21]
<p Guid="6365FC57-F476-4703-B9D4-1EB81288FF30" z2016-12-20="0" z2016-12-21="1" />
<p Guid="B38FA9DB-B4E1-4725-8F3B-3AF6E009C10A" z2016-12-20="1" z2016-12-21="0" />

जब आप for xml autoएसक्यूएल सर्वर का उपयोग कर रहे हैं तो वह आपके लिए करता है।


वह गुम लिंक था, xml पथ ('') के लिए, रूट ('रूट') अब काम कर रहा है।
बंकरबस्टर

6

पहला चरित्र यूनिकोड नहीं है, प्रति से। मेरा मतलब है, SQL सर्वर के भीतर XML में तकनीकी रूप से सभी वर्ण UTF-16 लिटिल एंडियन के रूप में एन्कोड किए गए हैं, इसलिए इस अर्थ में वे सभी यूनिकोड हैं। लेकिन, आप जो देख रहे हैं, वह केवल एक पात्र के लिए बची हुई धारणा है, इस मामले में "2", जिसका "32" का हेक्स / बाइनरी मान है।

समस्या बस यह है कि XML नाम एक संख्या से शुरू नहीं हो सकता है। निम्नलिखित परीक्षण दर्शाते हैं कि संख्या के साथ शुरू होने वाले एक विशेषता नाम या तत्व का नाम एक त्रुटि प्राप्त करता है, लेकिन एक अंडरस्कोर ( _) या एक अक्षर से शुरू करना ठीक है।

SELECT CONVERT(XML, N'<test><row 2016-12-17="2" /></test>');
/*
Msg 9455, Level 16, State 1, Line 10
XML parsing: line 1, character 12, illegal qualified name character
*/


SELECT CONVERT(XML, N'<test><2016>a</2016></test>');
/*
Msg 9455, Level 16, State 1, Line 10
XML parsing: line 1, character 8, illegal qualified name character
*/


SELECT CONVERT(XML, N'<test><row _2016-12-17="2" /></test>');
/*
<test>
  <row _2016-12-17="2" />
</test>
*/


SELECT CONVERT(XML, N'<test><row x2016-12-17="2" /></test>');
/*
<test>
  <row x2016-12-17="2" />
</test>
*/

तो, आपको स्तंभ नामों को किसी ऐसे चरित्र के साथ उपसर्ग करने की आवश्यकता है जो XML विशेषता या तत्व नाम के लिए प्रारंभिक वर्ण के रूप में मान्य है।


इसके अलावा, क्या आप सुनिश्चित हैं कि यह "काम" कर रहा है FOR XML AUTO? मैं जो देख सकता हूं, वह बस "अमान्य" वर्ण को रूपांतरित कर रहा है _x0032_:

SELECT tmp.* FROM (SELECT 2) tmp([2016]) FOR XML AUTO;

यह दिखाता है:

<tmp _x0032_016="2" />
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.