এসকিউএল সার্ভার ২০০৮-এ এক্সএমএল ক্ষেত্র থেকে মানগুলি নির্বাচন করুন


112

কেবলমাত্র আমার এক্সএমএল ক্ষেত্রটি দেখলে আমার সারিগুলি দেখতে দেখতে এ রকম দেখাচ্ছে:

<person><firstName>Jon</firstName><lastName>Johnson</lastName></person>
<person><firstName>Kathy</firstName><lastName>Carter</lastName></person>
<person><firstName>Bob</firstName><lastName>Burns</lastName></person>

মনে রাখবেন যে এগুলি আমার টেবিলের তিনটি সারি।

আমি একটি এসকিউএল ফলাফল হিসাবে টেবিল হিসাবে ফিরে আসতে চাই

Jon  | Johnson
Kathy| Carter
Bob  | Burns

কোন প্রশ্নটি এটি সম্পাদন করবে?


এক্সএমএলে সমস্ত উপাদান যুক্ত করার কোনও উপায় নেই? আপনি এক এক করে নির্দিষ্ট করতে হবে? এটি সত্যিই ক্লান্তিকর দ্রুত পায়। আপনি "টেবিল থেকে নির্বাচন করুন" করতে পারেন, মনে হচ্ছে আপনার পছন্দসই প্রতিটি উপাদান নির্দিষ্ট না করেই "সিলেক্ট এক্সএমএল। * এক্সএমএল থেকে" করতে সক্ষম হওয়া উচিত।
কিথ টাইলার

উত্তর:


157

দেওয়া হয়েছে যে এক্সএমএল ফিল্ডটির নাম দেওয়া হয়েছে 'xMLField' ...

SELECT 
[xmlField].value('(/person//firstName/node())[1]', 'nvarchar(max)') as FirstName,
[xmlField].value('(/person//lastName/node())[1]', 'nvarchar(max)') as LastName
FROM [myTable]

16
যদি এক্সএমএলফিল্ডে একাধিক <প্রেস> উপাদান থাকে তবে আপনাকে অবশ্যই নোড () ব্যবহার করতে হবে এবং ক্রস প্রয়োগ করতে হবে।
রিমাস রুসানু

এসকিউএল সার্ভার 2008 R2 এক্সপ্রেস, আমাকে তোমার সমাধান সঙ্গে এই ত্রুটি ফিরিয়ে দিয়েছে: The XQuery syntax '/function()' is not supported.; অন্যদিকে @ রেমাস রুসানু এটি করছে বলে মনে হচ্ছে :)
আরমিরানদা

2
উদ্ভট। এটি 102 বার ভোট হয়েছে, তবে এই উত্তরটি কেবল প্রথম এক্সএমএল রেকর্ড থেকে ডেটা ফেরত দেয় । এবং এটি কিছু [আমার টেবিল] টেবিলকে বোঝায় ... কোথা থেকে এলো ?!
মাইক গ্লেডহিল

আমি এটি বহুবার চেষ্টা করেছি এবং কখনও এটি কাজ করে নি। আমার এক্সএমএল হয় <BAM><Type>Electrical</Type><BaIds><a:int>7330</a:int></BaIds></BAM>, আমার নির্বাচন হয় select e.MessageData.value('(/BAM/Type)[1]', 'varchar(100)')। আমিও নির্বাচন চেষ্টা করেছি e.MessageData.value('(/BAM/Type/node())[1]', 'varchar(100)'), এবং '(//Type/node())[1]', '(./Type)[1]', এবং প্রত্যেক অন্যান্য সমন্বয় আমি মনে করতে পারেন। আমি যা পাই তা সবই NULL
JonathanPeel

1
@ মাইকগ্লেডহেল এটি আমার জন্য একাধিক এক্সএমএল রেকর্ড থেকে মানগুলি ফেরত দেয়। এছাড়াও ওপি যে টেবিল দেয় তার একমাত্র নাম হ'ল "আমার টেবিল" :)
পল

123

এক্সএমএল ডেটা একটি টেবিল 'টেবিল' থেকে আসে এবং এটি একটি কলামে 'ফিল্ডে' সংরক্ষণ করা হয় তা বিবেচনা করে: এক্সএমএল পদ্ধতিগুলি ব্যবহার করুন , এর সাথে মানগুলি উত্তোলন করুন xml.value(), প্রজেক্ট নোড সহ xml.nodes(), CROSS APPLYযোগ দিতে ব্যবহার করুন:

SELECT 
    p.value('(./firstName)[1]', 'VARCHAR(8000)') AS firstName,
    p.value('(./lastName)[1]', 'VARCHAR(8000)') AS lastName
FROM table 
    CROSS APPLY field.nodes('/person') t(p)

আপনি খনন করতে পারেন nodes()এবং cross applyযদি প্রতিটি ক্ষেত্রে সঠিকভাবে একটি উপাদান 'ব্যক্তি' থাকে। এক্সএমএল যদি কোনও পরিবর্তনশীল হয় তবে আপনি নির্বাচন করুন FROM @variable.nodes(...)এবং আপনার প্রয়োজন হবে না cross apply


1
আমি ভাবছি যে এই পদ্ধতিটি কতটা দক্ষ এবং এর চেয়ে আরও ভাল উপায় আছে কিনা। ক্রস অ্যাপ্লিকেশন XPath ফলাফলের সাথে একত্রিত হওয়ার ফলে মনে হচ্ছে এটির ফলে কোনও উত্স ক্ষুধার্ত ক্যোয়ারী হতে পারে।
redcalx

1
@ থেলোকস্টার: এটি সাধারণ ডেটা অ্যাক্সেস থেকে আলাদা নয়। এক্সএমএল কর্মক্ষমতা উন্নত করার কৌশলগুলি ডকুমেন্টেড। msdn.microsoft.com/en-us/library/ms345118%28SQL.90%29.aspx
রিমাস রুসানু

2
মনে রাখবেন যে আপনার এক্সএমএলে যদি এক্সএমএলএন নেমস্পেসগুলি সংজ্ঞায়িত করা থাকে তবে আপনাকে উপরের এক্সকুয়েরি (এক্সপথ) এক্সপ্রেশনটিতে সেগুলি সংজ্ঞায়িত করতে হবে। উদাহরণের জন্য stackoverflow.com/a/1302150/656010 দেখুন ।
টম ওয়েসন

আমার যা প্রয়োজন ছিল তার থেকে কিছুটা আলাদা, তবে এটি ছিল আমার একটি সমস্যার একটি নিখুঁত সমাধান যা একটি এক্সএমএল কলাম সহ একাধিক সারি ছিল - আমি সারিগুলির মধ্য দিয়ে লুপ করতে এবং এক্সএমএল কলামের মধ্যে থেকে ডেটা ক্ষেত্রগুলি বের করতে এবং এগুলিতে রেখে দিতে চেয়েছিলাম একটি সন্নিবেশ বিবৃতি। সুতরাং 5 টি সারি, প্রতিটি এক্সএমএল ক্ষেত্রে 3 কলামের ডেটা = 15 টি সন্নিবেশ করানো, নিখুঁত।
ডান রিচার্ডসন

17

এই পোস্টটি আমার সমস্যাটি সমাধান করতে সহায়ক যা কিছুটা আলাদা এক্সএমএল ফর্ম্যাট রয়েছে ... আমার এক্সএমএলে নীচের উদাহরণগুলির মতো কীগুলির একটি তালিকা রয়েছে এবং আমি ডেসিটব্যাচ নামের একটি সারণীতে সোর্সকিস কলামে এক্সএমএল সংরক্ষণ করি:

<k>1</k>
<k>2</k>
<k>3</k>

টেবিলটি তৈরি করুন এবং এটি কিছু ডেটা দিয়ে পপুলেট করুন:

CREATE TABLE dbo.DeleteBatch (
    ExecutionKey INT PRIMARY KEY,
    SourceKeys XML)

INSERT INTO dbo.DeleteBatch ( ExecutionKey, SourceKeys )
SELECT 1, 
    (CAST('<k>1</k><k>2</k><k>3</k>' AS XML))

INSERT INTO dbo.DeleteBatch ( ExecutionKey, SourceKeys )
SELECT 2, 
    (CAST('<k>100</k><k>101</k>' AS XML))

এক্সএমএল থেকে কীগুলি নির্বাচন করতে এখানে আমার এসকিউএল রয়েছে:

SELECT ExecutionKey, p.value('.', 'int') AS [Key]
FROM dbo.DeleteBatch
    CROSS APPLY SourceKeys.nodes('/k') t(p)

ক্যোয়ারির ফলাফলগুলি এখানে ...

এক্সিকিউশনকে কী
1 1
1 2
1 3
2 100
2 101

9

এটি আপনার প্রশ্নের উত্তর দিতে পারে:

select cast(xmlField as xml) xmlField into tmp from (
select '<person><firstName>Jon</firstName><lastName>Johnson</lastName></person>' xmlField
union select '<person><firstName>Kathy</firstName><lastName>Carter</lastName></person>'
union select '<person><firstName>Bob</firstName><lastName>Burns</lastName></person>'
) tb

SELECT
    xmlField.value('(person/firstName)[1]', 'nvarchar(max)') as FirstName
    ,xmlField.value('(person/lastName)[1]', 'nvarchar(max)') as LastName
FROM tmp

drop table tmp

6

বিস্ময় প্রকাশ করতে ব্যবহৃত। এটি আবিষ্কারের জন্য সত্যই একটি দরকারী থ্রেড ছিল।

আমি এখনও এই পরামর্শগুলির মধ্যে কিছু বিভ্রান্তিকর পেয়েছি। আমি যখনই স্ট্রিংয়ের valueসাথে ব্যবহার করেছি [1], এটি কেবলমাত্র প্রথম মানটি পুনরুদ্ধার করবে। এবং কিছু প্রস্তাবনা cross 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)

এবং এখানে ফলাফল:

এখানে চিত্র বর্ণনা লিখুন

এটি উদ্ভট সিনট্যাক্স, তবে একটি সুন্দর উদাহরণ সহ, এটি আপনার নিজের এসকিউএল সার্ভারের কার্যাদি যুক্ত করা যথেষ্ট সহজ।

যার বিষয়ে কথা বলছি, এখানে এই প্রশ্নের সঠিক উত্তর।

ধরে নিচ্ছি আপনার @xmlপ্রকারের ভেরিয়েবলটিতে আপনার এক্সএমএল ডেটা রয়েছে xml(উপরে আমার উদাহরণে প্রদর্শিত হিসাবে), আপনি কীভাবে প্রশ্নের উত্তর দেওয়া এক্সএমএল থেকে তিনটি সারি ডেটা ফেরত পাবেন:

SELECT 
    x.Rec.query('./firstName').value('.', 'nvarchar(2000)') AS 'FirstName',
    x.Rec.query('./lastName').value('.', 'nvarchar(2000)') AS 'LastName'
FROM @xml.nodes('/person') as x(Rec)

এখানে চিত্র বর্ণনা লিখুন


আমি দেখতে পাচ্ছি না এটি কীভাবে সঠিক উত্তর। ওপি XML টাইপযুক্ত কোনও সারণী থেকে একটি কলাম জিজ্ঞাসা করতে বলছে, এবং সেই ক্ষেত্রে আপনাকে [1]সূচী অরডিনালটি এটি 1 সারিটিতে ফিরে আসতে বাধ্য করতে হবে, বা আপনাকে একটি কলামটি nodes()পেতে এই কলামটি প্রয়োগ করতে হবে কাঠামো যাতে এর বিরুদ্ধে xpath চালাতে পারে। আপনার কোড প্রচুর পরিবর্তন ছাড়াই সেই দৃশ্যে অনুবাদ করে না। আপনি কোনও টেবিল কলাম নয়, একটি ভেরিয়েবল ব্যবহার করছেন। আপনি query()এক্সএমএল ফিরিয়ে দেয় এমন ফাংশনও অতিরিক্ত ব্যবহার করছেন । উদাহরণস্বরূপ আপনার সবেমাত্র থাকতে পারেx.Rec.value('(./firstName)[1]', 'nvarchar(2000)') AS FirstName
দাভোস

3

আপনি যদি কোনও এক্সএমএলকে কোনও মূল উপাদানটিতে মোড়াতে সক্ষম হন - বলুন তবে নীচেরটি আপনার সমাধান:

DECLARE @PersonsXml XML = '<persons><person><firstName>Jon</firstName><lastName>Johnson</lastName></person>
<person><firstName>Kathy</firstName><lastName>Carter</lastName></person>
<person><firstName>Bob</firstName><lastName>Burns</lastName></person></persons>'

SELECT  b.value('(./firstName/text())[1]','nvarchar(max)') as FirstName, b.value('(./lastName/text())[1]','nvarchar(max)') as LastName
FROM @PersonsXml.nodes('/persons/person') AS a(b)

এখানে চিত্র বর্ণনা লিখুন


3

এমএসএসকিউএল নিয়মিত এক্সপথ নিয়ম ব্যবহার করে:

  • নোডনাম "নোডনাম" নাম সহ সমস্ত নোড নির্বাচন করে
  • / রুট নোড থেকে নির্বাচন করে
  • // বর্তমান নোড থেকে নথিতে নোডগুলি নির্বাচন করে যা নির্বাচনের সাথে মেলে সেগুলি যেখানেই হোক না কেন match
  • । বর্তমান নোড নির্বাচন করে
  • .. বর্তমান নোডের পিতামাতাকে নির্বাচন করে
  • @ বৈশিষ্ট্য নির্বাচন করুন

W3Schools


2
SELECT 
cast(xmlField as xml).value('(/person//firstName/node())[1]', 'nvarchar(max)') as FirstName,
cast(xmlField as xml).value('(/person//lastName/node())[1]', 'nvarchar(max)') as LastName
FROM [myTable]

0

/ * এই উদাহরণটি স্কিমার সাথে একটি এক্সএমএল ভেরিয়েবল ব্যবহার করে * /

IF EXISTS (SELECT * FROM sys.xml_schema_collections 
           WHERE name = 'OrderingAfternoonTea')
BEGIN
    DROP XML SCHEMA COLLECTION dbo.OrderingAfternoonTea 
END
GO

CREATE XML SCHEMA COLLECTION dbo.OrderingAfternoonTea AS
N'<?xml version="1.0" encoding="UTF-16" ?>
  <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
     targetNamespace="http://Tfor2.com/schemas/actions/orderAfternoonTea"
     xmlns="http://Tfor2.com/schemas/actions/orderAfternoonTea"
     xmlns:TFor2="http://Tfor2.com/schemas/actions/orderAfternoonTea"
     elementFormDefault="qualified"
     version="0.10"
   > 
    <xsd:complexType name="AfternoonTeaOrderType">
       <xsd:sequence>
         <xsd:element name="potsOfTea" type="xsd:int"/>
         <xsd:element name="cakes" type="xsd:int"/>
         <xsd:element name="fruitedSconesWithCream" type="xsd:int"/>
         <xsd:element name="jams" type="xsd:string"/>
      </xsd:sequence>
      <xsd:attribute name="schemaVersion" type="xsd:long" use="required"/>
    </xsd:complexType>

    <xsd:element name="afternoonTeaOrder"
                 type="TFor2:AfternoonTeaOrderType"/>

  </xsd:schema>' ;
GO

DECLARE @potsOfTea int;
DECLARE @cakes int;
DECLARE @fruitedSconesWithCream int;
DECLARE @jams nvarchar(128);

DECLARE @RequestMsg NVARCHAR(2048);
DECLARE @RequestXml XML(dbo.OrderingAfternoonTea);

set @potsOfTea = 5;
set @cakes = 7;
set @fruitedSconesWithCream = 25;
set @jams = N'medlar jelly, quince and mulberry';

SELECT @RequestMsg = N'<?xml version="1.0" encoding="utf-16" ?>
<TFor2:afternoonTeaOrder schemaVersion="10"
    xmlns:TFor2="http://Tfor2.com/schemas/actions/orderAfternoonTea">
    <TFor2:potsOfTea>' + CAST(@potsOfTea as NVARCHAR(20)) 
        + '</TFor2:potsOfTea>
    <TFor2:cakes>' + CAST(@cakes as NVARCHAR(20)) + '</TFor2:cakes>
    <TFor2:fruitedSconesWithCream>' 
        + CAST(@fruitedSconesWithCream as NVARCHAR(20))
        + '</TFor2:fruitedSconesWithCream>
    <TFor2:jams>' + @jams + '</TFor2:jams>
</TFor2:afternoonTeaOrder>';

SELECT @RequestXml  = CAST(CAST(@RequestMsg AS VARBINARY(MAX)) AS XML) ;

with xmlnamespaces('http://Tfor2.com/schemas/actions/orderAfternoonTea'
                    as tea)
select
    cast( x.Rec.value('.[1]/@schemaVersion','nvarchar(20)') as bigint )
        as schemaVersion,
    cast( x.Rec.query('./tea:potsOfTea')
               .value('.','nvarchar(20)') as bigint ) as potsOfTea,
    cast( x.Rec.query('./tea:cakes')
               .value('.','nvarchar(20)') as bigint )  as cakes,
    cast( x.Rec.query('./tea:fruitedSconesWithCream')
               .value('.','nvarchar(20)') as bigint ) 
      as fruitedSconesWithCream,
    x.Rec.query('./tea:jams').value('.','nvarchar(50)')  as jams
from @RequestXml.nodes('/tea:afternoonTeaOrder')  as x(Rec);

select @RequestXml.query('/*')
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.