۱۳۸۸/۰۷/۳۰

به روز رساني فيلدهاي XML در SQL Server - قسمت دوم


قسمت اول را در اين آدرس مي‌توانيد مطالعه نمائيد.

در ادامه قسمت اول، اگر بخواهيم نود جديدي را به فيلد XML موجود اضافه كنيم، روش انجام آن به صورت زير است (يكي از روش‌ها البته):

DECLARE @tblTest AS TABLE (xmlField XML)

INSERT INTO @tblTest
(
xmlField
)
VALUES
(
'<Sample>
<Node1>Value1</Node1>
<Node2>Value2</Node2>
<Node3>OldValue</Node3>
</Sample>'
)

DECLARE @Name NVARCHAR(50)
SELECT @Name = 'Vahid'

UPDATE @tblTest
SET xmlField.modify(
'insert element Node4 {sql:variable("@Name")} as last into
(/Sample)[1]'
)

SELECT tt.xmlField
FROM @tblTest tt

كه حاصل آن (افزوده شدن يك المان جديد به نام Node4 بر اساس مقدار متغير Name در انتهاي ليست) به صورت زير مي‌باشد:

<Sample>
<Node1>Value1</Node1>
<Node2>Value2</Node2>
<Node3>OldValue</Node3>
<Node4>Vahid</Node4>
</Sample>

سؤال 1 :
اگر بخواهيم نام Node4 نيز متغير باشد به چه صورتي بايد مساله را حل كرد؟
در اين حالت بايد از كوئري‌هاي دايناميك استفاده كرد. بايد يك رشته را ايجاد (كل عبارت update بايد يك رشته شود) و سپس از دستور exec كمك گرفت و البته بايد دقت داشت در اين حالت كار encoding كاركترهاي غيرمجاز در XML را بايد خودمان انجام دهيم.

سؤال 2:
اگر بخواهيم نام نودها و مقادير آن‌ها را به صورت يك جدول معمولي بازگشت دهيم به چه صورتي بايد عمل كرد؟

DECLARE @XML AS XML

SELECT @XML = tt.xmlField
FROM @tblTest tt

SELECT t.c.value('local-name(..)', 'varchar(max)') AS ParentNodeName,
t.c.value('local-name(.)', 'varchar(max)') AS NodeName,
t.c.value('text()[1]', 'varchar(max)') AS NodeText

FROM @XML.nodes('/*/*') AS t(c)

كه پس از اجراي آن خواهيم داشت:

ParentNodeName - NodeName - NodeText
Sample Node1 Value1
Sample Node2 Value2
Sample Node3 OldValue
Sample Node4 Vahid