এসকিউএল সার্ভারে টেবিল থেকে এক্সএমএল মান এবং বৈশিষ্ট্যের জন্য কীভাবে জিজ্ঞাসা করবেন?


89

আমার একটি টেবিল রয়েছে যাতে 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()অ্যাগ্রিগেশন। তবে আপাতত আমি একটি এক্সএমএল কলামটি জিজ্ঞাসা করার চেষ্টা করছি ।

সিউডো কোডে, আমি এরকম কিছু চেষ্টা করব:

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

তবে যে এসকিউএল ক্যোয়ারি কাজ করে না:

Msg 2396, স্তর 16, রাজ্য 1, লাইন 2
এক্সকিউরি [Sqm.data.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

তবে এটি কার্যকর হয় না:

এমএসজি 2389, স্তর 16, রাজ্য 1, লাইন 3 এক্সকিউরি [স্কয়ার.ডাটা.ভ্যালু ()]:
'মান ()' এর জন্য একটি সিঙ্গলটন (বা খালি অনুক্রম) প্রয়োজন, 'এক্সডিটি: অব টাইপড অ্যাটমিক *' টাইপের অপারেন্ড পাওয়া গেছে

উত্তর:


114

আসলে আপনি আপনার লক্ষ্যের কাছাকাছি, আপনার সারিগুলি বিভক্ত করার জন্য আপনাকে নোড () পদ্ধতিটি ব্যবহার করতে হবে এবং তারপরে মানগুলি পেতে হবে:

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


4
আমি কীভাবে নোডের "মান" পাব ? select m.*এটি নির্মিত গোপন, যাদুকরী, মধ্যবর্তী টেবিল দেখার কোনও উপায় নেই বলে মনে হয় । কোনও উপাদানটির মান জিজ্ঞাসা করার সিনট্যাক্সটি কী? যেমন এর মান <Metric>8675309</Metric>হয় "8675309"
ইয়ান বয়েড

4
@ ইয়ানবয়েড দুঃখিত, এটি মিস করেছেন, আপডেট দেখুন। তুমি ব্যবহার করতে পার '.' বা পাঠ্য যদি সেখানে নেস্টেড উপাদান থাকতে পারে
রোমান পেকার

4
কি alias লেখা না s, mএবং cএই প্রশ্নের সাথে প্রতিনিধিত্ব?
ইয়ান আর ও'ব্রায়েন

4
@ IanR.O'Brien mresultset দ্বারা ফিরিয়ে দেওয়া হয় nodes()ফাংশন, sহয় sqmটেবিল নিজে cresultset দ্বারা ফিরে মধ্যে ডাটা টাইপ XML সঙ্গে কলাম nodes()ফাংশন
রোমান Pekar

11

আমি খুব অনুরূপ কিছু করার চেষ্টা করেছি তবে নোডগুলি ব্যবহার করছি না। তবে আমার এক্সএমএল স্ট্রাকচারটি কিছুটা আলাদা।

আপনার কাছে এটি এমন:

<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

আমার কাছে এটি বাইরের প্রয়োগ বা ক্রস প্রয়োগ ব্যবহারের চেয়ে অনেক কম বিভ্রান্তিকর।

আমি আশা করি এটি সহজ সমাধানের সন্ধানে অন্য কাউকে সহায়তা করে!


4
কোডটি খোলার বন্ধনীগুলি মিস করে। /text()পারফরম্যান্স বৃদ্ধির জন্য আইডি ইত্যাদির পরেও সংযোজন করুন
ড্যানি রানার

এটি সর্বাধিক সোজা for ধন্যবাদ, নিখুঁতভাবে কাজ করেছেন।
এসই

আমরা এই পদ্ধতির সাথে কোনও এক্সএমএল টাইপ কলাম সহ একটি টেবিলটি কীভাবে জিজ্ঞাসা করব? ধন্যবাদ.
এফএমএফএফ 7:44

10

এর valueপরিবর্তে ব্যবহার করুন query(এক্সকিউরিতে ফিরে আসার জন্য নোডের সূচক নির্দিষ্ট করতে হবে এবং দ্বিতীয় প্যারামিটার হিসাবে ফিরে আসতে 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)

9

কিছু লোক কেন এক্সএমএলকে মানগুলির সারণীতে রূপান্তর করতে cross applyবা ব্যবহারের পরামর্শ দিচ্ছেন তা আমি বুঝতে পারি না outer apply। আমার জন্য, এটি সবেমাত্র অনেক বেশি ডেটা ফিরিয়ে এনেছে।

আপনি কীভাবে কোনও 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)এক্সএমএল কাস্টের আগে নেস্টেড কাস্ট ?
এভিলডিআর

আমরা এই পদ্ধতির সাথে কোনও এক্সএমএল টাইপ কলাম সহ একটি টেবিলটি কীভাবে জিজ্ঞাসা করব? ধন্যবাদ.
এফএমএফএফ

@ এফএমএফএফ এই পদ্ধতিটি ক্রস অ্যাপ্লিকেশন ব্যবহার করে অন্য সকলের কাছে অভিন্ন।
SgtWilko
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.