SQL सर्वर में तालिका से Xml मान और विशेषताओं के लिए क्वेरी कैसे करें?


88

मेरे पास एक तालिका है जिसमें एक Xmlकॉलम है:

SELECT * 
FROM Sqm

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

एक xmlपंक्ति के डेटा का एक नमूना होगा:

<Sqm version="1.2">
  <Metrics>
    <Metric id="TransactionCleanupThread.RecordUsedTransactionShift" type="timer" unit="µs" count="1" sum="21490"   average="21490"   minValue="73701"    maxValue="73701"                               >73701</Metric>
    <Metric id="TransactionCleanupThread.RefundOldTrans"             type="timer" unit="µs" count="1" sum="184487"  average="184487"  minValue="632704"   maxValue="632704"                              >632704</Metric>
    <Metric id="Database.CreateConnection_SaveContextUserGUID"       type="timer" unit="µs" count="2" sum="7562"    average="3781"    minValue="12928"    maxValue="13006"    standardDeviation="16"     >12967</Metric>
    <Metric id="Global.CurrentUser"                                  type="timer" unit="µs" count="6" sum="4022464" average="670411"  minValue="15"       maxValue="13794345" standardDeviation="1642047">2299194</Metric>
    <Metric id="Global.CurrentUser_FetchIdentityFromDatabase"        type="timer" unit="µs" count="1" sum="4010057" average="4010057" minValue="13752614" maxValue="13752614"                            >13752614</Metric>
  </Metrics>
</Sqm>

इस डेटा के मामले में, मैं चाहूंगा:

SqmId  id                                                   type   unit  count  sum      minValue  maxValue  standardDeviation  Value
=====  ===================================================  =====  ====  =====  ======   ========  ========  =================  ======
1      TransactionCleanupThread.RecordUsedTransactionShift  timer  µs    1      21490    73701     73701     NULL               73701
1      TransactionCleanupThread.RefundOldTrans              timer  µs    1      184487   632704    632704    NULL               632704
1      Database.CreateConnection_SaveContextUserGUID        timer  µs    2      7562     12928     13006     16                 12967
1      Global.CurrentUser                                   timer  µs    6      4022464  15        13794345  1642047            2299194
1      Global.CurrentUser_FetchIdentityFromDatabase         timer  µs    1      4010057  13752614  13752614  NULL               13752614
2      ...

अंत में मैं वास्तव में प्रदर्शन किया जाएगा SUM(), MIN(), MAX()एकत्रीकरण। लेकिन अभी के लिए मैं सिर्फ एक xml कॉलम को क्वेरी करने की कोशिश कर रहा हूं ।

छद्म कोड में, मैं कुछ इस तरह की कोशिश करेंगे:

SELECT
    SqmId,
    Data.query('/Sqm/Metrics/Metric/@id') AS id,
    Data.query('/Sqm/Metrics/Metric/@type') AS type,
    Data.query('/Sqm/Metrics/Metric/@unit') AS unit,
    Data.query('/Sqm/Metrics/Metric/@sum') AS sum,
    Data.query('/Sqm/Metrics/Metric/@count') AS count,
    Data.query('/Sqm/Metrics/Metric/@minValue') AS minValue,
    Data.query('/Sqm/Metrics/Metric/@maxValue') AS maxValue,
    Data.query('/Sqm/Metrics/Metric/@standardDeviation') AS standardDeviation,
    Data.query('/Sqm/Metrics/Metric') AS value
FROM Sqm

लेकिन वह SQL क्वेरी काम नहीं करती है:

Msg 2396, स्तर 16, राज्य 1, पंक्ति 2
XQuery [Sqm.data.query ()]: गुण एक तत्व के बाहर प्रकट नहीं हो सकता है

मैंने शिकार किया है, और यह आश्चर्यजनक है कि खराब तरीके से प्रलेखित, या जांच की गई, एक्सएमएल क्वेरी क्या है। तालिका को क्वेरी करने के बजाय अधिकांश संसाधन , एक चर क्वेरी ; जो मैं नहीं कर रहा हूं। अधिकांश संसाधन केवल पढ़ने के मूल्यों के बजाय फ़िल्टरिंग और चयन के लिए xml क्वेरी का उपयोग करते हैं। अधिकांश संसाधन वास्तविक मानों के बजाय हार्ड-कोडेड चाइल्ड नोड्स (इंडेक्स द्वारा) पढ़ते हैं।

संबंधित संसाधन जो मैंने पढ़ा

अद्यतन: .query के बजाय

मैंने इसके .valueस्थान पर बेतरतीब ढंग से उपयोग करने की कोशिश की .query:

SELECT
    Sqm.SqmId,
    Data.value('/Sqm/Metrics/Metric/@id', 'varchar(max)') AS id,
    Data.value('/Sqm/Metrics/Metric/@type', 'varchar(max)') AS type,
    Data.value('/Sqm/Metrics/Metric/@unit', 'varchar(max)') AS unit,
    Data.value('/Sqm/Metrics/Metric/@sum', 'varchar(max)') AS sum,
    Data.value('/Sqm/Metrics/Metric/@count', 'varchar(max)') AS count,
    Data.value('/Sqm/Metrics/Metric/@minValue', 'varchar(max)') AS minValue,
    Data.value('/Sqm/Metrics/Metric/@maxValue', 'varchar(max)') AS maxValue,
    Data.value('/Sqm/Metrics/Metric/@standardDeviation', 'varchar(max)') AS standardDeviation,
    Data.value('/Sqm/Metrics/Metric', 'varchar(max)') AS value
FROM Sqm

लेकिन वह भी काम नहीं करता है:

Msg 2389, लेवल 16, स्टेट 1, लाइन 3 XQuery [Sqm.data.value ()]:
'value ()' के लिए एक सिंगलटन (या खाली अनुक्रम) की आवश्यकता होती है, जो टाइप 'xdt: untypedtomic *' का ऑपरेंड पाया जाता है।

जवाबों:


113

वास्तव में आप अपने लक्ष्य के करीब हैं, आपको अपनी पंक्तियों को विभाजित करने और फिर मान प्राप्त करने के लिए केवल नोड्स () विधि का उपयोग करने की आवश्यकता है :

select
    s.SqmId,
    m.c.value('@id', 'varchar(max)') as id,
    m.c.value('@type', 'varchar(max)') as type,
    m.c.value('@unit', 'varchar(max)') as unit,
    m.c.value('@sum', 'varchar(max)') as [sum],
    m.c.value('@count', 'varchar(max)') as [count],
    m.c.value('@minValue', 'varchar(max)') as minValue,
    m.c.value('@maxValue', 'varchar(max)') as maxValue,
    m.c.value('.', 'nvarchar(max)') as Value,
    m.c.value('(text())[1]', 'nvarchar(max)') as Value2
from sqm as s
    outer apply s.data.nodes('Sqm/Metrics/Metric') as m(c)

sql fiddle demo


1
मुझे नोड का "मूल्य" कैसे मिलेगा ? ऐसा लगता है कि select m.*इसके द्वारा बनाई गई गुप्त, जादुई, मध्यवर्ती तालिका को देखने का कोई तरीका नहीं है । किसी तत्व के मूल्य के लिए वाक्य रचना क्या है? उदाहरण के लिए "8675309" का मान <Metric>8675309</Metric>है
इयान बॉयड

1
@IanBoyd क्षमा करें, याद किया, अद्यतन देखें। आप उपयोग कर सकते हैं '।' या पाठ अगर वहाँ नेस्टेड तत्व हो सकते हैं
रोमन पाकर

2
उपनाम s, mऔर cइस क्वेरी में क्या दर्शाते हैं?
इयान आर। ओ'ब्रायन

3
@ IanR.O'Brien mresultset द्वारा दिया जाता है nodes()समारोह, sहै sqmतालिका में ही, cresultset द्वारा लौटाए में डेटा प्रकार एक्सएमएल के साथ स्तंभ है nodes()समारोह
रोमन Pekar

11

मैं कुछ ऐसा ही करने की कोशिश कर रहा हूं, लेकिन नोड्स का उपयोग नहीं कर रहा हूं। हालाँकि, मेरी xml संरचना थोड़ी अलग है।

आपके पास ऐसा है:

<Metrics>
    <Metric id="TransactionCleanupThread.RefundOldTrans" type="timer" ...>

अगर यह इस तरह से थे:

<Metrics>
    <Metric>
        <id>TransactionCleanupThread.RefundOldTrans</id>
        <type>timer</type>
        .
        .
        .

तब आप बस इस एसक्यूएल स्टेटमेंट का उपयोग कर सकते हैं।

SELECT
    Sqm.SqmId,
    Data.value('(/Sqm/Metrics/Metric/id)[1]', 'varchar(max)') as id,
    Data.value('(/Sqm/Metrics/Metric/type)[1]', 'varchar(max)') AS type,
    Data.value('(/Sqm/Metrics/Metric/unit)[1]', 'varchar(max)') AS unit,
    Data.value('(/Sqm/Metrics/Metric/sum)[1]', 'varchar(max)') AS sum,
    Data.value('(/Sqm/Metrics/Metric/count)[1]', 'varchar(max)') AS count,
    Data.value('(/Sqm/Metrics/Metric/minValue)[1]', 'varchar(max)') AS minValue,
    Data.value('(/Sqm/Metrics/Metric/maxValue)[1]', 'varchar(max)') AS maxValue,
    Data.value('(/Sqm/Metrics/Metric/stdDeviation)[1]', 'varchar(max)') AS stdDeviation,
FROM Sqm

मेरे लिए यह बाहरी अनुप्रयोग या क्रॉस लागू का उपयोग करने की तुलना में बहुत कम भ्रमित है।

मुझे आशा है कि यह किसी और को सरल समाधान की तलाश में मदद करता है!


1
कोड खुलने वाले कोष्ठक को याद करता है। /text()प्रदर्शन में वृद्धि के लिए आईडी आदि के बाद भी परिशिष्ट
डैनी रंचर

यह सबसे स्ट्रेपफॉरवर्ड है। धन्यवाद, पूरी तरह से काम किया।
एसई

हम इस दृष्टिकोण के साथ एक्सएमएल टाइप कॉलम वाली तालिका को कैसे क्वेरी कर सकते हैं? धन्यवाद।
FMFF

10

के valueबजाय का उपयोग queryकरना चाहिए (XTD में लौटने के लिए नोड के सूचकांक को निर्दिष्ट करना चाहिए और साथ ही दूसरे पैरामीटर के रूप में लौटने के लिए sql डेटा प्रकार को पास करना चाहिए):

select
    xt.Id
    , x.m.value( '@id[1]', 'varchar(max)' ) MetricId
from
    XmlTest xt
    cross apply xt.XmlData.nodes( '/Sqm/Metrics/Metric' ) x(m)

8

मुझे समझ नहीं आता कि कुछ लोग xml को मानों की तालिका में बदलने cross applyया उपयोग outer applyकरने का सुझाव क्यों दे रहे हैं । मेरे लिए, यह सिर्फ बहुत अधिक डेटा वापस लाए।

यहाँ मेरा उदाहरण है कि आप एक xmlवस्तु कैसे बनाएँगे , फिर उसे एक तालिका में बदल दें।

(मैंने अपने xml स्ट्रिंग में स्थान जोड़ दिए हैं, बस पढ़ने में आसान बनाने के लिए।)

DECLARE @str nvarchar(2000)

SET @str = ''
SET @str = @str + '<users>'
SET @str = @str + '  <user>'
SET @str = @str + '     <firstName>Mike</firstName>'
SET @str = @str + '     <lastName>Gledhill</lastName>'
SET @str = @str + '     <age>31</age>'
SET @str = @str + '  </user>'
SET @str = @str + '  <user>'
SET @str = @str + '     <firstName>Mark</firstName>'
SET @str = @str + '     <lastName>Stevens</lastName>'
SET @str = @str + '     <age>42</age>'
SET @str = @str + '  </user>'
SET @str = @str + '  <user>'
SET @str = @str + '     <firstName>Sarah</firstName>'
SET @str = @str + '     <lastName>Brown</lastName>'
SET @str = @str + '     <age>23</age>'
SET @str = @str + '  </user>'
SET @str = @str + '</users>'

DECLARE @xml xml
SELECT @xml = CAST(CAST(@str AS VARBINARY(MAX)) AS XML) 

--  Iterate through each of the "users\user" records in our XML
SELECT 
    x.Rec.query('./firstName').value('.', 'nvarchar(2000)') AS 'FirstName',
    x.Rec.query('./lastName').value('.', 'nvarchar(2000)') AS 'LastName',
    x.Rec.query('./age').value('.', 'int') AS 'Age'
FROM @xml.nodes('/users/user') as x(Rec)

और यहाँ उत्पादन है:

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


जिज्ञासु ... क्यों Varbinary(max)xml कास्ट करने से पहले नेस्टेड डाली कृपया?
EvilDr

हम इस दृष्टिकोण के साथ एक्सएमएल टाइप कॉलम वाली तालिका को कैसे क्वेरी कर सकते हैं? धन्यवाद।
FMFF
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.