3

SQL Server 2008に、XMLデータをXML列に格納するテーブルがあります。典型的なXMLフラグメントは次のとおりです。

<validation>
    <Field1 author="56234" date="20120101" />
    <Field2 author="23232" date="20120101" />
        [...etc...]
</validation>

私が解決しようとしていること(そしてそれを行う方法がわかりません)は、INNER JOINを使用してこのデータを別のテーブルに選択し、結果セットのXMLデータを変更することです。つまり、次のようになります。

<validation>
    <Field1 author="56234" date="20120101" authorFullName="Bob Smith" />
    <Field2 author="23232" date="20120101" authorFullName="Jane Hill" />
        [...etc...]
</validation>

これで、XMLデータをレコードセットに直接プルして内部結合することができることがわかりCROSS APPLYました。たとえば、次のようにします。

select xmldata.a, people.personname
    from xmldata
        cross apply xmldata.x.nodes('/validation/node()') vdata(fielddata)
        inner join people 
            on people.personid = vdata.fielddata.value('@author','NVARCHAR(20)')

しかし、私が実際にやりたいのは、元のXMLを返すことですが、新しい属性を追加して、people.PersonNameを新しい@authorFullName属性にマッピングします。

私は構文を完全に理解することができません(またはそれが実際に可能であるとしても)。私はでやろうと思ってcross applyいます-に基づいた何かmodifyinsert attribute

select xmldata.a, xmldata.x
    from xmldata
        cross apply xmldata.x.modify('insert attribute authorFullName {sql:column("people.personfullname")} into /validation/node()')
        inner join people 
            on people.personid = [...what goes here?...]

しかし、構文を正しく理解することは私を逃れています。私はますますそれが不可能だと考えています。これを2つのクエリで実行し、結果を非SQLビジネスロジックにマージすることをお勧めします。

4

1 に答える 1

1

modifyselectステートメントでは使用できません。

modify()メソッド(xmlデータ型)から

xmlデータ型のmodify()メソッドは、UPDATEステートメントのSET句でのみ使用できます。

2つの選択肢があると思います。

  1. XMLを細断処理し、使用for xml pathしてXMLドキュメントを希望どおりに再構築し、適切な場所に個人名を挿入します。
  2. XMLを変数に抽出し、使用set @XML.modify(insert...して個人名を挿入します。

2番目のオプションを選択する場合は、挿入のexpression2(XML DML)が単一ノードである必要があるため、whileループを使用する必要があります。

オプション2のコードは次のようになります。

declare @XML xml
declare @C int
declare @PersonName varchar(50)
declare @PersonID int

-- Store your XML in a XML variable
set @XML = 
'<validation>
    <Field1 author="56234" date="20120101" />
    <Field2 author="23232" date="20120101" />
</validation>'

-- Get number of nodes to be modified
set @C = @XML.value('count(/validation/*)', 'int')

-- For each node
while @C > 0
begin
  -- Get person id from XML
  set @PersonID = @XML.value('(/validation/*[sql:variable("@C")]/@author)[1]', 'int')

  -- Get person name
  select @PersonName = personname
  from people
  where personid = @PersonID 

  if @@rowcount = 1
  begin
    -- add person name to XML
    set @XML.modify('insert attribute authorFullName {sql:variable("@PersonName")} 
                        into (/validation/*[sql:variable("@C")])[1]')
  end

  -- next node
  set @C = @C - 1
end
于 2012-09-05T17:04:29.880 に答える