Share via


PATH モードの使用

FOR XML を使用した XML の構築」で説明したように、PATH モードを使用すると、要素と属性の組み合わせが容易になります。入れ子構造を使用することで、複雑なプロパティも容易に表現できるようになります。FOR XML EXPLICIT モードのクエリを使用してこのような XML を行セットから作成することもできますが、煩雑になりかねない EXPLICIT モードのクエリに比べて PATH モードでは同じことを簡潔に行うことができます。PATH モードに、入れ子の FOR XML クエリと、xml 型のインスタンスを返す TYPE ディレクティブを組み合わせることで、簡潔なクエリを記述できます。

PATH モードでは、列名または列の別名が XPath 式として処理されます。XPath 式は XML に値がどのようにマップされているかを示します。各 XPath 式は、行要素に対して相対的に生成されるノードの種類 (属性、要素、スカラ値など) および名前と階層を提供する相対 XPath です。

このトピックでは、行セット内の各列をマップする際、次の列に適用される条件について説明します。

  • 名前のない列
  • 名前のある列
  • 名前をワイルドカード文字 (*) で指定した列
  • XPath ノード テストの名前が付いた列
  • パスを data() で指定した列名
  • 既定で NULL 値が含まれる列

名前のない列

名前のない列はインラインになります。たとえば、計算列または入れ子になったスカラ クエリで列の別名を指定しないと、名前のない列が生成されます。列が xml 型の場合、そのデータ型のインスタンスの内容が挿入されます。それ以外の型の場合は、列の内容がテキスト ノードとして挿入されます。

SELECT 2+2
FOR XML PATH

上のクエリは、次の XML を生成します。既定では、行セットの行ごとに 1 つの <row> 要素が、結果の XML に生成されます。これは RAW モードと同じ動作です。

<row>4</row>

次のクエリは 3 列の行セットを返します。3 番目の名前がない列には、XML データが含まれています。PATH モードにより、xml 型のインスタンスが挿入されます。

SELECT ProductModelID,
       Name,
       Instructions.query('declare namespace MI="https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelManuInstructions";
                /MI:root/MI:Location 
              ') 
FROM Production.ProductModel
WHERE ProductModelID=7
FOR XML PATH 
go

結果の一部を次に示します。

<row>
  <ProductModelID>7</ProductModelID>
  <Name>HL Touring Frame</Name>
  <MI:Location ...LocationID="10" ...></MI:Location>
  <MI:Location ...LocationID="20" ...></MI:Location>
   ...
</row>

名前のある列

行セット内の名前のある列が、大文字と小文字を区別して結果の XML にマップされる条件を次に示します。

  • 列名がアット マーク (@) で始まる場合
  • 列名がアット マーク (@) で始まらない場合
  • 列名がアット マーク (@) で始まらず、スラッシュ (/) を含む場合
  • 複数の列に同一のプレフィックスがある場合
  • 名前の異なる列がある場合

列名がアット マーク (@) で始まる場合

列名がアット マーク (@) で始まり、スラッシュ (/) を含んでいない場合は、<row> 要素の属性が作成され、対応する列値が値として設定されます。たとえば、次のクエリは 2 列 (@PmId、Name) の行セットを返します。結果の XML では、対応する <row> 要素に PmId 属性が追加され、この属性に ProductModelID の値が設定されます。

SELECT ProductModelID as "@PmId",
       Name
FROM Production.ProductModel
WHERE ProductModelID=7
FOR XML PATH 
go

結果を次に示します。

<row PmId="7">
  <Name>HL Touring Frame</Name>
</row>

属性は、同一レベルでは要素ノード、テキスト ノードなどの他の種類のノードよりも前に指定する必要があります。次のクエリはエラーを返します。

SELECT Name,
       ProductModelID as "@PmId"
FROM Production.ProductModel
WHERE ProductModelID=7
FOR XML PATH 
go

列名がアット マーク (@) で始まらない場合

列名がアット マーク (@) で始まらず、XPath の任意のノード テストでもなく、スラッシュ (/) も含んでいない場合、行要素 (既定では <row>) のサブ要素になる XML 要素が作成されます。

次のクエリでは列名 result が指定されています。したがって、<row> 要素には、<result> 子要素が追加されます。

SELECT 2+2 as result
for xml PATH

結果を次に示します。

<row>
  <result>4</result>
</row>

次のクエリでは、xml 型の Instructions 列に対して指定した XQuery から返される XML に対応する列の名前として、ManuWorkCenterInformation を指定しています。したがって、<row> 要素の子要素として、<ManuWorkCenterInformation> 要素が追加されます。

SELECT 
       ProductModelID,
       Name,
       Instructions.query('declare namespace MI="https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelManuInstructions";
                /MI:root/MI:Location 
              ') as ManuWorkCenterInformation
FROM Production.ProductModel
WHERE ProductModelID=7
FOR XML PATH 
go

結果を次に示します。

<row>
  <ProductModelID>7</ProductModelID>
  <Name>HL Touring Frame</Name>
  <ManuWorkCenterInformation>
    <MI:Location ...LocationID="10" ...></MI:Location>
    <MI:Location ...LocationID="20" ...></MI:Location>
     ...
  </ManuWorkCenterInformation>
</row>

列名がアット マーク (@) で始まらず、スラッシュ (/) を含む場合

列名がアット マーク (@) で始まらず、スラッシュ (/) を含んでいる場合、列名は XML 階層を示します。たとえば、列名を "Name1/Name2/Name3.../Namen" とすると、Namei は、i = 1 の場合は現在の行要素の入れ子である要素を表し、それ以外の場合は Namei-1 要素の下にある要素を表します。Namen が '@' で始まる場合は、Namen-1 要素の属性にマップされます。

たとえば次のクエリは、従業員の ID と名前を返します。従業員名は、First、Middle、および Last から構成される複合型の要素 EmpName で表現されます。

SELECT EmployeeID "@EmpID", 
       FirstName  "EmpName/First", 
       MiddleName "EmpName/Middle", 
       LastName   "EmpName/Last"
FROM   HumanResources.Employee E, Person.Contact C
WHERE  E.EmployeeID = C.ContactID
AND    E.EmployeeID=1
FOR XML PATH

PATH モードでは、列名は XML を作成する際のパスとして使用されます。従業員 ID の値を格納している列の名前は '@' で始まっているため、EmpID が属性として <row> 要素に追加されます。それ以外のすべての列の列名には、階層を示すスラッシュ ('/') が含まれています。結果の XML では、<row> 要素の下に <EmpName> 子要素があり、<EmpName> の下に子要素 <First>、<Middle>、および <Last> が生成されます。

<row EmpID="1">
  <EmpName>
    <First>Gustavo</First>
    <Last>Achong</Last>
  </EmpName>
</row>

この従業員のミドル ネームは NULL です。既定で NULL 値は、要素や属性がない状態にマップされます。値が NULL であっても要素を生成するには、次のクエリのように XSINIL を指定した ELEMENTS ディレクティブを使用します。

SELECT EmployeeID "@EmpID", 
       FirstName  "EmpName/First", 
       MiddleName "EmpName/Middle", 
       LastName   "EmpName/Last"
FROM   HumanResources.Employee E, Person.Contact C
WHERE  E.EmployeeID = C.ContactID
AND    E.EmployeeID=1
FOR XML PATH, ELEMENTS XSINIL

結果を次に示します。

<row xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
      EmpID="1">
  <EmpName>
    <First>Gustavo</First>
    <Middle xsi:nil="true" />
    <Last>Achong</Last>
  </EmpName>
</row>

PATH モードの既定では要素中心の XML が生成されます。したがって、PATH モードのクエリで ELEMENTS ディレクティブを指定しても効力はありません。ただし、前のクエリで示したように、ELEMENTS ディレクティブを XSINIL と組み合わせると、NULL 値に対して要素を生成する場合に便利です。

次のクエリでは従業員の ID と名前以外に住所を取得します。住所列の列名のパスにより、<row> 要素に <Address> 子要素が追加され、<Address> 要素の子要素として詳しい住所が追加されます。

SELECT EmployeeID   "@EmpID", 
       FirstName    "EmpName/First", 
       MiddleName   "EmpName/Middle", 
       LastName     "EmpName/Last",
       AddressLine1 "Address/AddrLine1",
       AddressLine2 "Address/AddrLIne2",
       City         "Address/City"
FROM   HumanResources.Employee E, Person.Contact C, Person.Address A
WHERE  E.EmployeeID = C.ContactID
AND    E.AddressID = A.AddressID
AND    E.EmployeeID=1
FOR XML PATH

結果を次に示します。

<row EmpID="1">
  <EmpName>
    <First>Gustavo</First>
    <Last>Achong</Last>
  </EmpName>
  <Address>
    <AddrLine1>7726 Driftwood Drive</AddrLine1>
    <City>Monroe</City>
  </Address>
</row>

複数の列に同一のパス プレフィックスがある場合

連続した複数の列に同一のパス プレフィックスがある場合、これらの列は 1 つの名前でグループ化されます。異なる名前空間プレフィックスが使用されている場合は、同一の名前空間にバインドされていても、パスは異なるものと見なされます。上のクエリで、FirstName 列、MiddleName 列、および LastName 列にはいずれも EmpName プレフィックスがあるので、これらは <EmpName> 要素の子として追加されます。このことは、上記の例の <Address> 要素の生成にも該当します。

名前の異なる列がある場合

変更を加えた次のクエリに示すように、異なる名前の列が間にある場合、グループは分割されます。上のクエリで示した FirstName、MiddleName、および LastName から構成されるグループは、FirstName 列と MiddleName 列の間に住所列を追加すると分割されます。

SELECT EmployeeID "@EmpID", 
       FirstName "EmpName/First", 
       AddressLine1 "Address/AddrLine1",
       AddressLine2 "Address/AddrLIne2",
       City "Address/City",
       MiddleName "EmpName/Middle", 
       LastName "EmpName/Last"
FROM   HumanResources.EmployeeAddress E, Person.Contact C, Person.Address A
WHERE  E.EmployeeID = C.ContactID
AND    E.AddressID = A.AddressID
AND    E.EmployeeID=1
FOR XML PATH

このクエリの結果、<EmpName> 要素が 2 つ作成されます。最初の <EmpName> 要素には <FirstName> 子要素が、2 番目の <EmpName> 要素には <MiddleName> 子要素と <LastName> 子要素が含まれます。

結果を次に示します。

<row EmpID="1">
  <EmpName>
    <First>Gustavo</First>
  </EmpName>
  <Address>
    <AddrLine1>7726 Driftwood Drive</AddrLine1>
    <City>Monroe</City>
  </Address>
  <EmpName>
    <Last>Achong</Last>
  </EmpName>
</row>

名前をワイルドカード文字 (*) で指定した列

列名にワイルドカード文字 (*) を指定した場合は、列名が指定されていない場合のように、列の内容が挿入されます。xml 型以外の列の場合は、次の例で示すように内容がテキスト ノードとして挿入されます。

SELECT EmployeeID "@EmpID", 
       FirstName "*", 
       MiddleName "*", 
       LastName "*"
FROM   HumanResources.Employee E, Person.Contact C
WHERE  E.EmployeeID = C.ContactID
AND    E.EmployeeID=1
FOR XML PATH

結果を次に示します。

<row EmpID="1">GustavoAchong</row>

xml 型の列の場合、対応する XML ツリーが挿入されます。たとえば次のクエリでは、Instructions 列に対する XQuery が返す XML を格納する列名として "*" を指定しています。

SELECT 
       ProductModelID,
       Name,
       Instructions.query('declare namespace MI="https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelManuInstructions"
                /MI:root/MI:Location 
              ') as "*"
FROM Production.ProductModel
WHERE ProductModelID=7
FOR XML PATH 
go

結果は次のとおりです。XQuery が返した XML は、囲み要素なしで挿入されます。

<row>
  <ProductModelID>7</ProductModelID>
  <Name>HL Touring Frame</Name>
  <MI:Location LocationID="10">...</MI:Location>
  <MI:Location LocationID="20">...</MI:Location>
...
</row>

XPath ノード テストの名前が付いた列

XPath ノード テストのいずれかが列名である場合、内容は次の表に示すようにマップされます。

列名がいずれかの XPath ノード テストであれば、対応するノードに内容がマップされます。列の SQL 型が xml の場合は、エラーが返されます。

列名 動作

text()

text() という名前の列では、列内の文字列値がテキスト ノードとして追加されます。

comment()

comment() という名前の列では、列内の文字列値が XML のコメントとして追加されます。

node()

node() という名前の列では、列名がワイルドカード文字 (*) の場合と同じ結果が返されます。

processing-instruction(name)

処理命令を名前とする列では、列内の文字列値が、処理命令ターゲット名に対応する PI 値として追加されます。

パスを data() として指定した列の名前

列名として指定したパスが "data()" の場合、生成される XML では列の値がアトミック値として処理されます。シリアル化時の後続アイテムもアトミック値である場合は、空白文字が XML に追加されます。これはリスト状の要素値または属性値を作成する場合に有用です。次のクエリでは、製品モデルの ID および名前と、そのモデルに含まれる製品のリストを取得します。

SELECT ProductModelID       as "@ProductModelID",
       Name                 as "@ProductModelName",
      (SELECT ProductID as "data()"
       FROM   Production.Product
       WHERE  Production.Product.ProductModelID = 
              Production.ProductModel.ProductModelID
      FOR XML PATH (''))    as "@ProductIDs"
FROM  Production.ProductModel
WHERE ProductModelID= 7 
FOR XML PATH('ProductModelData')

入れ子の内側の SELECT では、製品 ID のリストを取得しています。製品 ID の列名が "data()" と指定されています。PATH モードでは空文字列が行の要素名に指定されるので、ここでは行要素は生成されません。代わりに、親の SELECT で指定した <ProductModelData> 行要素の ProductIDs 属性に設定された値が返されます。結果を次に示します。

<ProductModelData ProductModelID="7" 
                  ProductModelName="HL Touring Frame" 
                  ProductIDs="885 887 888 889 890 891 892 893" />

NULL 値が含まれる列の既定動作

既定で、列内の NULL 値は、属性、ノード、または要素がない状態にマップされます。この既定動作を変更するには、次のクエリに示すように、ELEMENTS ディレクティブで要素中心の XML を要求し、NULL 値に対しても要素の追加を要求する XSINIL を指定します。

SELECT EmployeeID as "@EmpID", 
       FirstName  as "EmpName/First", 
       MiddleName as "EmpName/Middle", 
       LastName   as "EmpName/Last"
FROM   HumanResources.Employee E, Person.Contact C
WHERE  E.EmployeeID = C.ContactID
AND    E.EmployeeID=1
FOR XML PATH, ELEMENTS XSINIL

結果を次に示します。XSINIL を指定しないと、<Middle> 要素は出力されません。

<row xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" EmpID="1">
  <EmpName>
    <First>Gustavo</First>
    <Middle xsi:nil="true" />
    <Last>Achong</Last>
  </EmpName>
</row>

名前空間のサポート

このバージョンでは、WITH NAMESPACES を使用することで PATH モードでの名前空間がサポートされます。たとえば、次のクエリは WITH NAMESPACES 構文を使用して、後続の SELECT ステートメントで使用できる名前空間 ("a:") を宣言する例を示しています。

WITH XMLNAMESPACES('a' as a)
SELECT 1 as 'a:b'
FOR XML PATH

次のサンプルでは、PATH モードで SELECT クエリから XML を生成する例を示します。ProductModel テーブルの Instructions 列に格納されている自転車製造手順 XML ドキュメントに対して、多数のこのようなクエリが指定されているものとします。仕様書 XML の詳細については、「AdventureWorks データベースの xml データ型表現」を参照してください。

A. PATH モードの単純なクエリの指定

次のクエリには FOR XML PATH モードが指定されています。

SELECT 
       ProductModelID,
       Name
FROM Production.ProductModel
WHERE ProductModelID=122 or ProductModelID=119
FOR XML PATH
go

次の結果は、要素中心の XML です。結果の行セットの列値は、それぞれ 1 つの要素に格納されています。SELECT 句に列の別名が指定されていないので、生成される子要素の名前は SELECT 句の対応する列名と同じになっています。行セットの各行には <row> タグが追加されます。

<row>
  <ProductModelID>122</ProductModelID>
  <Name>All-Purpose Bike Stand</Name>
</row>
<row>
  <ProductModelID>119</ProductModelID>
  <Name>Bike Wash</Name>
</row>

次の結果は、ELEMENTS オプションを指定した RAW モードのクエリと同じです。返される結果は、結果セットの各行に既定の <row> 要素が追加された要素中心の XML です。

SELECT ProductModelID,
       Name
FROM Production.ProductModel
WHERE ProductModelID=122 or ProductModelID=119
FOR XML RAW, ELEMENTS

必要に応じて、行要素の名前を指定して既定の <row> を上書きできます。たとえば、次のクエリは行セットの行ごとに <ProductModel> 要素を返します。

SELECT ProductModelID,
       Name
FROM Production.ProductModel
WHERE ProductModelID=122 or ProductModelID=119
FOR XML PATH ('ProductModel')
Go

結果の XML には指定した行要素名が使用されます。

<ProductModel>
  <ProductModelID>122</ProductModelID>
  <Name>All-Purpose Bike Stand</Name>
</ProductModel>
<ProductModel>
  <ProductModelID>119</ProductModelID>
  <Name>Bike Wash</Name>
</ProductModel>

長さがゼロの文字列を指定すると、囲み要素は生成されません。

SELECT ProductModelID,
       Name
FROM Production.ProductModel
WHERE ProductModelID=122 or ProductModelID=119
FOR XML PATH ('')
Go

結果を次に示します。

<ProductModelID>122</ProductModelID>
<Name>All-Purpose Bike Stand</Name>
<ProductModelID>119</ProductModelID>
<Name>Bike Wash</Name>

B. XPath 形式の列名の指定

次のクエリでは、ProductModelID 列に指定した名前が '@' で始まり、スラッシュ ('/') を含んでいません。したがって、結果の XML では、<row> 要素の属性が生成され、対応する列値が設定されます。

SELECT ProductModelID as "@id",
       Name
FROM Production.ProductModel
WHERE ProductModelID=122 or ProductModelID=119
FOR XML PATH ('ProductModelData')
go

結果を次に示します。

< ProductModelData id="122">
    <Name>All-Purpose Bike Stand</Name>
</ ProductModelData >
< ProductModelData id="119">
    <Name>Bike Wash</Name>
</ ProductModelData >

FOR XML で root オプションを指定すると、単一の最上位要素を追加できます。

SELECT ProductModelID as "@id",
       Name
FROM Production.ProductModel
WHERE ProductModelID=122 or ProductModelID=119
FOR XML PATH ('ProductModelData'), root ('Root')
go

階層を生成するには、PATH 形式の構文を使用できます。たとえば、Name 列の列名を "SomeChild/ModelName" に変更すると、次に示すように階層を伴う XML が返されます。

<Root>
  <ProductModelData id="122">
    <SomeChild>
      <ModelName>All-Purpose Bike Stand</ModelName>
    </SomeChild>
  </ProductModelData>
  <ProductModelData id="119">
    <SomeChild>
      <ModelName>Bike Wash</ModelName>
    </SomeChild>
  </ProductModelData>
</Root>

次のクエリは、指定した製品モデルの ID および名前以外に、その製品モデルに対応する製造手順書の場所を返します。Instructions 列が xml 型なので、xml データ型の query() メソッドを指定して場所を取得します。

SELECT ProductModelID as "@id",
       Name,
       Instructions.query('declare namespace MI="https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelManuInstructions";
                /MI:root/MI:Location 
              ') as ManuInstr
FROM Production.ProductModel
WHERE ProductModelID=7
FOR XML PATH ('ProductModelData'), root ('Root')
go

結果の一部を次に示します。列名として ManuInstr が指定されているので、query() メソッドが返す XML は次に示すように <ManuInstr> タグで囲まれています。

<Root>
  <ProductModelData id="7">
    <Name>HL Touring Frame</Name>
    <ManuInstr>
      <MI:Location xmlns:MI="https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelManuInstructions" 
        <MI:step>...</MI:step>...
      </MI:Location>
      ...
    </ManuInstr>
  </ProductModelData>
</Root>

上記の FOR XML クエリで、<Root> 要素と <ProductModelData> 要素に対応する名前空間を含めることができます。そのためには、WITH XMLNAMESPACES で名前空間のバインドのためのプレフィックスを定義しておき、FOR XML クエリで使用します。詳細については、「WITH XMLNAMESPACES を使用した名前空間の追加」を参照してください。

WITH XMLNAMESPACES (
   'uri1' as ns1,  
   'uri2' as ns2,
   'https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelManuInstructions' as MI)
SELECT ProductModelID as "ns1:ProductModelID",
       Name           as "ns1:Name",
       Instructions.query('
                /MI:root/MI:Location 
              ') 
FROM Production.ProductModel
WHERE ProductModelID=7
FOR XML PATH ('ns2:ProductInfo'), root('ns1:root')
go

WITH XMLNAMESPACES では MI プレフィックスも定義されています。したがって、指定された xml 型の query() メソッドにおいて、クエリ プロローグでこのプレフィックスは定義されていません。結果を次に示します。

<ns1:root xmlns:MI="https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelManuInstructions" xmlns="uri2" xmlns:ns2="uri2" xmlns:ns1="uri1">
  <ns2:ProductInfo>
    <ns1:ProductModelID>7</ns1:ProductModelID>
    <ns1:Name>HL Touring Frame</ns1:Name>
    <MI:Location xmlns:MI="https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelManuInstructions" 
       LaborHours="2.5" LotSize="100" MachineHours="3" SetupHours="0.5" LocationID="10" >
       <MI:step>
          Insert <MI:material>aluminum sheet MS-2341</MI:material> into the <MI:tool>T-85A framing tool</MI:tool>. 
       </MI:step>
         ...
    </MI:Location>
     ...
  </ns2:ProductInfo>
</ns1:root>

C. PATH モードを使用した値リストの生成

次のクエリは、製品モデルごとに製品 ID の値リストを生成します。また、次の XML フラグメントで示すように製品 ID ごとに <ProductName> 子要素が生成されます。

<ProductModelData ProductModelID="7" ProductModelName="..."  
                  ProductIDs="product id list in the product model" >
  <ProductName>...</ProductName>
  <ProductName>...</ProductName>
  ...
</ProductModelData>

求める XML を生成するクエリを次に示します。

SELECT ProductModelID     as "@ProductModelID",
       Name               as "@ProductModelName",
      (SELECT ProductID as "data()"
       FROM   Production.Product
       WHERE  Production.Product.ProductModelID = 
              Production.ProductModel.ProductModelID
       FOR XML PATH ('')) as "@ProductIDs",
       (SELECT Name as "ProductName"
       FROM   Production.Product
       WHERE  Production.Product.ProductModelID = 
              Production.ProductModel.ProductModelID
        FOR XML PATH ('')) as "ProductNames"
FROM   Production.ProductModel
WHERE  ProductModelID= 7 or ProductModelID=9
FOR XML PATH('ProductModelData')

上のクエリに関して、次の点に注意してください。

  • 最初の SELECT サブクエリは、列名として data() を使用することで ProductID の一覧を返しています。FOR XML PATH の行要素名として空文字列が指定されているので、要素は生成されません。代わりに、値リストが ProductID 属性に割り当てられています。
  • 2 番目の SELECT サブクエリは、該当する製品モデルに含まれる製品名を取得します。列名として ProductNames を指定しているので、生成した <ProductName> 要素は <ProductNames> 要素に囲まれた状態で返しています。

結果の一部を次に示します。

<ProductModelData PId="7" 
                  ProductModelName="HL Touring Frame" 
                  ProductIDs="885 887 ...">
  <ProductNames>
    &lt;ProductName&gt;HL Touring Frame - Yellow, 60&lt;/ProductName&gt;
    &lt;ProductName&gt;HL Touring Frame - Yellow, 46&lt;/ProductName&gt;</ProductNames>
    ...
</ProductModelData>
<ProductModelData PId="9" 
                  ProductModelName="LL Road Frame" 
                  ProductIDs="722 723 724 ...">
  <ProductNames>
     &lt;ProductName&gt;LL Road Frame - Black, 58&lt;/ProductName&gt;
     &lt;ProductName&gt;LL Road Frame - Black, 60&lt;/ProductName&gt;
     &lt;ProductName&gt;LL Road Frame - Black, 62&lt;/ProductName&gt;
     ...
  </ProductNames>
</ProductModelData>

製品名を構成するサブクエリは、結果として返す文字列をエンティティ表記に変換してから XML に追加しています。TYPE ディレクティブ FOR XML PATH (''), type を追加した場合、結果は xml 型で返され、エンティティ表記への変換は行われません。

SELECT ProductModelID as "@ProductModelID",
      Name as "@ProductModelName",
      (SELECT ProductID as "data()"
       FROM   Production.Product
       WHERE  Production.Product.ProductModelID = 
              Production.ProductModel.ProductModelID
       FOR XML PATH ('')
       ) as "@ProductIDs",
       (
       SELECT Name as "ProductName"
       FROM   Production.Product
       WHERE  Production.Product.ProductModelID = 
              Production.ProductModel.ProductModelID
       FOR XML PATH (''), type
       ) as "ProductNames"
       
FROM Production.ProductModel
WHERE ProductModelID= 7 or ProductModelID=9
FOR XML PATH('ProductModelData')

D. 結果の XML への名前空間の追加

WITH XMLNAMESPACES を使用した名前空間の追加」で説明したように、WITH XMLNAMESPACES を使用すると PATH モードのクエリに名前空間を含めることができます。たとえば、SELECT 句で指定する名前に名前空間のプレフィックスを追加できます。次の PATH モードのクエリを実行すると、名前空間を伴った XML が生成されます。

SELECT 'en'    as "English/@xml:lang",
       'food'  as "English",
       'ger'   as "German/@xml:lang",
       'Essen' as "German"
FOR XML PATH ('Translation')
go

<English> 要素に追加されている @xml:lang 属性は、定義済みの XML 名前空間で定義されています。

結果を次に示します。

<Translation>
  <English xml:lang="en">food</English>
  <German xml:lang="ger">Essen</German>
</Translation>

次のクエリは例 C と似ていますが、結果の XML に名前空間を含めるために WITH XMLNAMESPACES を使用している点が異なります。詳細については、「WITH XMLNAMESPACES を使用した名前空間の追加」を参照してください。

WITH XMLNAMESPACES ('uri1' as ns1,  DEFAULT 'uri2')
SELECT ProductModelID as "@ns1:ProductModelID",
      Name as "@ns1:ProductModelName",
      (SELECT ProductID as "data()"
       FROM   Production.Product
       WHERE  Production.Product.ProductModelID = 
              Production.ProductModel.ProductModelID
       FOR XML PATH ('')
       ) as "@ns1:ProductIDs",
       (
       SELECT ProductID as "@ns1:ProductID", 
              Name as "@ns1:ProductName"
       FROM   Production.Product
       WHERE  Production.Product.ProductModelID = 
              Production.ProductModel.ProductModelID
       FOR XML PATH , type 
       ) as "ns1:ProductNames"
       
FROM Production.ProductModel
WHERE ProductModelID= 7 or ProductModelID=9
FOR XML PATH('ProductModelData'), root('root')

結果を次に示します。

<root xmlns="uri2" xmlns:ns1="uri1">
  <ProductModelData ns1:ProductModelID="7" ns1:ProductModelName="HL Touring Frame" ns1:ProductIDs="885 887 888 889 890 891 892 893">
    <ns1:ProductNames>
      <row xmlns="uri2" xmlns:ns1="uri1" ns1:ProductID="885" ns1:ProductName="HL Touring Frame - Yellow, 60" />
      <row xmlns="uri2" xmlns:ns1="uri1" ns1:ProductID="887" ns1:ProductName="HL Touring Frame - Yellow, 46" />
       ...
    </ns1:ProductNames>
  </ProductModelData>
  <ProductModelData ns1:ProductModelID="9" ns1:ProductModelName="LL Road Frame" ns1:ProductIDs="722 723 724 725 726 727 728 729 730 736 737 738">
    <ns1:ProductNames>
      <row xmlns="uri2" xmlns:ns1="uri1" ns1:ProductID="722" ns1:ProductName="LL Road Frame - Black, 58" />
        ...
    </ns1:ProductNames>
  </ProductModelData>
</root>

参照

関連項目

FOR XML を使用した XML の構築

概念

WITH XMLNAMESPACES を使用した名前空間の追加

その他の技術情報

SELECT (Transact-SQL)

ヘルプおよび情報

SQL Server 2005 の参考資料の入手