SequenceType 式 (XQuery)
XQuery では、値は常にシーケンスです。値の型をシーケンス型と呼びます。シーケンス型は instance of XQuery 式で使用できます。XQuery 式で型を参照する必要があるときは、XQuery 仕様に記載されている SequenceType 構文を使用します。
また、cast as XQuery 式ではアトミック型の名前を使用できます。SQL Server では、SequenceType での instance of と cast as XQuery 式が部分的にサポートされます。
instance of 演算子
instance of 演算子は、指定された式の値の型の動的な型 (ランタイム型) を決定するために使用できます。次に例を示します。
Expression instance of SequenceType[Occurrence indicator]
instance of 演算子の Occurrence indicator により、カーディナリティ (結果のシーケンスのアイテム数) が指定されることに注意してください。この値を指定しないと、カーディナリティは 1 と想定されます。SQL Server では、疑問符 (?) 出現インジケータのみがサポートされます。? 出現インジケータは、Expression から 0 または 1 つのアイテムが返されることを示します。? 出現インジケータを指定すると、Expression から 1 つの値が返されるか空のシーケンスが返されるかに関係なく、Expression の型が指定した SequenceType と一致すると instance of から True が返されます。
? 出現インジケータを指定しないと、Expression の型が指定した Type と一致し、Expression から 1 つの値が返される場合にのみ、sequence of から True が返されます。
注 プラス記号 (+) とアスタリスク (*) の出現インジケータは、SQL Server ではサポートされません。
次の例は、instance of XQuery 演算子の使用方法を示しています。
例 A
次の例では、xml 型の変数を作成し、その変数に対してクエリを指定しています。このクエリ式では、instance of 演算子を指定して、最初のオペランドから返される値の動的な型と 2 つ目のオペランドに指定した型が一致するかどうかを判断します。
125 という値は指定した型 xs:integer のインスタンスなので、次のクエリから True が返されます。
declare @x xml
set @x=''
select @x.query('125 instance of xs:integer')
go
次のクエリでは、最初のオペランドの式 /a[1] から返される値が要素なので True が返されます。
declare @x xml
set @x='<a>1</a>'
select @x.query('/a[1] instance of element()')
go
同様に、次のクエリでは最初の式に含まれている式の値の型が属性型なので、instance of から True が返されます。
declare @x xml
set @x='<a attr1="x">1</a>'
select @x.query('/a[1]/@attr1 instance of attribute()')
go
次の例では、式 data(/a[1] から xdt:untypedAtomic に型指定されたアトミック値が返されます。したがって、instance of から True が返されます。
declare @x xml
set @x='<a>1</a>'
select @x.query('data(/a[1]) instance of xdt:untypedAtomic')
go
次のクエリでは、式 data(/a[1]/@attrA から型指定されていないアトミック値が返されます。したがって、instance of から True が返されます。
declare @x xml
set @x='<a attrA="X">1</a>'
select @x.query('data(/a[1]/@attrA) instance of xdt:untypedAtomic')
go
例 B
この例では、AdventureWorks サンプル データベース内の、型指定された XML 列に対してクエリを実行しています。クエリ対象の列に関連付けられた XML スキーマ コレクションにより、型指定情報が提供されます。
この式では、data() から ProductModelID 属性の型指定された値が返されます。ProductModelID 属性の型は、クエリしている列に関連付けられたスキーマに従って xs:string になります。したがって、instance of から True が返されます。
SELECT CatalogDescription.query('
declare namespace PD="https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelDescription";
data(/PD:ProductDescription[1]/@ProductModelID) instance of xs:string
') as Result
FROM Production.ProductModel
WHERE ProductModelID = 19
詳細については、「型指定された XML と型指定されていない XML の比較」を参照してください。CatalogDescription 列に関連付けられた XML スキーマ コレクションの詳細については、「ProductModel.CatalogDescription xml 列について」を参照してください。
次のクエリでは、ブール式の instance of を使用して LocationID 属性が xs:integer 型かどうかを判断しています。
SELECT Instructions.query('
declare namespace AWMI="https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelManuInstructions";
/AWMI:root[1]/AWMI:Location[1]/@LocationID instance of attribute(LocationID,xs:integer)
') as Result
FROM Production.ProductModel
WHERE ProductModelID=7
次のクエリは、CatalogDescription 型が指定された XML 列に対して指定されています。この列に関連付けられた XML スキーマ コレクションにより、型指定情報が提供されます。XML スキーマ コレクションの詳細については、「ProductModel.CatalogDescription xml 列について」を参照してください。
このクエリでは、instance of 式で element(ElementName, ElementType?) テストを使用して、特定の名前と型の要素ノードが /PD:ProductDescription[1] から返されることを確認します。
SELECT CatalogDescription.query('
declare namespace PD="https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelDescription";
/PD:ProductDescription[1] instance of element(PD:ProductDescription, PD:ProductDescription?)
') as Result
FROM Production.ProductModel
where ProductModelID=19
クエリから True が返されます。
例 C
SQL Server の instance of 式は共用体型を使用する場合に制限があります。具体的には、要素または属性の型が共用体型の場合、instance of で正確な型が判断されません。したがって、SequenceType で使用されているアトミック型が、simpleType 階層内にある式の実際の型の最上位の親でない限り、クエリから False が返されます。つまり、SequenceType に指定したアトミック型は、anySimpleType の直接の子である必要があります。型階層の詳細については、「XQuery での型キャストの規則」を参照してください。
次のクエリの例では、以下の操作を実行します。
整数型または文字列型などに定義される共用体型を使用して XML スキーマ コレクションを作成します。
XML スキーマ コレクションを使用して、型指定された xml 変数を宣言します。
その変数にサンプル XML インスタンスを割り当てます。
変数にクエリして、共用体型を処理するときの instance of の動作を示します。
クエリは次のとおりです。
CREATE XML SCHEMA COLLECTION MyTestSchema AS '
<schema xmlns="http://www.w3.org/2001/XMLSchema" targetNamespace="http://ns" xmlns:ns="http://ns">
<simpleType name="MyUnionType">
<union memberTypes="integer string"/>
</simpleType>
<element name="TestElement" type="ns:MyUnionType"/>
</schema>'
Go
次のクエリでは、instance of 式に指定している SequenceType が、指定した式の実際の型の最上位の親ではないので False が返されます。つまり、<TestElement> の値は整数型で、最上位の親は xs:decimal 型です。しかし、この型が instance of 演算子の 2 つ目のオペランドとして指定されていません。
SET QUOTED_IDENTIFIER ON
DECLARE @var XML(MyTestSchema)
SET @var = '<TestElement xmlns="http://ns">123</TestElement>'
SELECT @var.query('declare namespace ns="http://ns"
data(/ns:TestElement[1]) instance of xs:integer')
go
xs:integer の最上位の親は xs:decimal なので、クエリを変更し、xs:decimal をクエリの SequenceType に指定すると、クエリから True が返されます。
SET QUOTED_IDENTIFIER ON
DECLARE @var XML(MyTestSchema)
SET @var = '<TestElement xmlns="http://ns">123</TestElement>'
SELECT @var.query('declare namespace ns="http://ns"
data(/ns:TestElement[1]) instance of xs:decimal')
go
例 D
この例では、最初に XML スキーマ コレクションを作成し、その XML スキーマ コレクションを使用して xml 変数の型を指定しています。次に、型指定された xml 変数にクエリして、instance of 機能を示しています。
次の XML スキーマ コレクションでは、単純型 myType と myType 型の要素 <root> を定義しています。
drop xml schema collection SC
go
CREATE XML SCHEMA COLLECTION SC AS '
<schema xmlns="http://www.w3.org/2001/XMLSchema" targetNamespace="myNS" xmlns:ns="myNS"
xmlns:s="https://schemas.microsoft.com/sqlserver/2004/sqltypes">
<import namespace="https://schemas.microsoft.com/sqlserver/2004/sqltypes"/>
<simpleType name="myType">
<restriction base="s:varchar">
<maxLength value="20"/>
</restriction>
</simpleType>
<element name="root" type="ns:myType"/>
</schema>'
Go
ここで、型指定された xml 変数を作成し、クエリを実行します。
DECLARE @var XML(SC)
SET @var = '<root xmlns="myNS">My data</root>'
SELECT @var.query('declare namespace sqltypes = "https://schemas.microsoft.com/sqlserver/2004/sqltypes";
declare namespace ns="myNS";
data(/ns:root[1]) instance of ns:myType')
go
myType 型は制限により、sqltypes スキーマで定義されている varchar 型から派生しているので、instance of から True が返されます。
DECLARE @var XML(SC)
SET @var = '<root xmlns="myNS">My data</root>'
SELECT @var.query('declare namespace sqltypes = "https://schemas.microsoft.com/sqlserver/2004/sqltypes";
declare namespace ns="myNS";
data(/ns:root[1]) instance of sqltypes:varchar?')
go
例 E
次の例では、式で IDREFS 属性のいずれかの値を取得し、instance of を使用して値が IDREF 型かどうかを判断しています。この例では、次の操作が実行されます。
<Customer> 要素に OrderList IDREFS 型属性があり、<Order> 要素に OrderID ID 型属性がある XML スキーマ コレクションを作成します。
型指定された xml 変数を作成し、その変数にサンプル XML インスタンスを割り当てます。
変数に対してクエリを指定します。このクエリ式により、最初の <Customer> の OrderList IDRERS 型属性から最初の注文 ID 値が取得されます。取得される値は IDREF 型です。したがって、instance of から True が返されます。
create xml schema collection SC as
'<schema xmlns="http://www.w3.org/2001/XMLSchema" xmlns:Customers="Customers" targetNamespace="Customers">
<element name="Customers" type="Customers:CustomersType"/>
<complexType name="CustomersType">
<sequence>
<element name="Customer" type="Customers:CustomerType" minOccurs="0" maxOccurs="unbounded" />
</sequence>
</complexType>
<complexType name="OrderType">
<sequence minOccurs="0" maxOccurs="unbounded">
<choice>
<element name="OrderValue" type="integer" minOccurs="0" maxOccurs="unbounded"/>
</choice>
</sequence>
<attribute name="OrderID" type="ID" />
</complexType>
<complexType name="CustomerType">
<sequence minOccurs="0" maxOccurs="unbounded">
<choice>
<element name="spouse" type="string" minOccurs="0" maxOccurs="unbounded"/>
<element name="Order" type="Customers:OrderType" minOccurs="0" maxOccurs="unbounded"/>
</choice>
</sequence>
<attribute name="CustomerID" type="string" />
<attribute name="OrderList" type="IDREFS" />
</complexType>
</schema>'
go
declare @x xml(SC)
set @x='<CustOrders:Customers xmlns:CustOrders="Customers">
<Customer CustomerID="C1" OrderList="OrderA OrderB" >
<spouse>Jenny</spouse>
<Order OrderID="OrderA"><OrderValue>11</OrderValue></Order>
<Order OrderID="OrderB"><OrderValue>22</OrderValue></Order>
</Customer>
<Customer CustomerID="C2" OrderList="OrderC OrderD" >
<spouse>John</spouse>
<Order OrderID="OrderC"><OrderValue>33</OrderValue></Order>
<Order OrderID="OrderD"><OrderValue>44</OrderValue></Order>
</Customer>
<Customer CustomerID="C3" OrderList="OrderE OrderF" >
<spouse>Jane</spouse>
<Order OrderID="OrderE"><OrderValue>55</OrderValue></Order>
<Order OrderID="OrderF"><OrderValue>55</OrderValue></Order>
</Customer>
<Customer CustomerID="C4" OrderList="OrderG" >
<spouse>Tim</spouse>
<Order OrderID="OrderG"><OrderValue>66</OrderValue></Order>
</Customer>
<Customer CustomerID="C5" >
</Customer>
<Customer CustomerID="C6" >
</Customer>
<Customer CustomerID="C7" >
</Customer>
</CustOrders:Customers>'
select @x.query(' declare namespace CustOrders="Customers";
data(CustOrders:Customers/Customer[1]/@OrderList)[1] instance of xs:IDREF ? ') as XML_result
実装の制限事項
制限事項を次に示します。
schema-element() シーケンス型と schema-attribute() シーケンス型は、instance of 演算子の比較では使用できません。
(1,2) instance of xs:integer* などの完全なシーケンスはサポートされません。
型名を指定する element() シーケンス型の形式 (element(ElementName, TypeName) など) を使用するときは、型を疑問符 (?) で修飾する必要があります。たとえば、element(Title, xs:string?) は要素が NULL であることを示します。SQL Server では、instance of を使用した xsi:nil プロパティのランタイム検出がサポートされていません。
Expression の値が共用体型として型指定された要素または属性の値である場合、SQL Server では、派生された型ではなく、値の型の派生元のプリミティブ型しか識別できません。たとえば、<e1> が (xs:integer | xs:string) の静的な型を持つように定義されている場合、次の式では False が返されます。
data(<e1>123</e1>) instance of xs:integer
ただし、data(<e1>123</e1>) instance of xs:decimal の場合は True が返されます。
processing-instruction() シーケンス型と document-node() シーケンス型では、引数を指定しない形式のみを使用できます。たとえば、processing-instruction() は使用できますが、processing-instruction('abc') は使用できません。
cast as 演算子
cast as 式は、値を特定のデータ型に変換する場合に使用できます。次に例を示します。
Expression cast as AtomicType?
SQL Server では、AtomicType の後に疑問符 (?) が必要です。たとえば、次のクエリで示すように、"2" cast as xs:integer? では文字列値が整数型に変換されます。
declare @x xml
set @x=''
select @x.query('"2" cast as xs:integer?')
次のクエリでは、data() により、文字列型である ProductModelID 属性の型指定された値が返されます。cast as演算子により、値が xs:integer に変換されます。
WITH XMLNAMESPACES ('https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelDescription' AS PD)
SELECT CatalogDescription.query('
data(/PD:ProductDescription[1]/@ProductModelID) cast as xs:integer?
') as Result
FROM Production.ProductModel
WHERE ProductModelID = 19
このクエリでは、data() を明示的に使用する必要はありません。cast as 式により、入力式で暗黙のアトミック化が実行されます。
コンストラクタ関数
アトミック型のコンストラクタ関数を使用できます。たとえば、"2" cast as xs:integer? のように cast as 演算子を使用するのではなく、次の例で示すように xs:integer() コンストラクタ関数を使用できます。
declare @x xml
set @x=''
select @x.query('xs:integer("2")')
次の例では、2000-01-01Z に等しい xs:date 型の値が返されます。
declare @x xml
set @x=''
select @x.query('xs:date("2000-01-01Z")')
また、ユーザー定義アトミック型のコンストラクタを使用することもできます。たとえば、XML データ型に関連付けられた XML スキーマ コレクションで単純型が定義されている場合、myType() コンストラクタを使用して単純型の値が返されるようにできます。
実装の制限事項
XQuery 式 typeswitch、castable、および treat はサポートされません。
cast as ではアトミック型の後に疑問符 (?) が必要です。
xs:QName はキャストの型としてはサポートされません。代わりに expanded-QName を使用します。
xs:date、xs:time、および xs:datetime には、Z で示されるタイム ゾーンが必要です。
タイム ゾーンが指定されていないので、次のクエリは失敗します。
DECLARE @var XML SET @var = '' SELECT @var.query(' <a>{xs:date("2002-05-25")}</a>') go
値に Z タイム ゾーン インジケータを追加すると、クエリが機能します。
DECLARE @var XML SET @var = '' SELECT @var.query(' <a>{xs:date("2002-05-25Z")}</a>') go
結果を次に示します。
<a>2002-05-25Z</a>