Выражения SequenceType (XQuery)
Область применения: SQL Server
В XQuery значение всегда является последовательностью. Тип значения называется типом последовательности. Тип последовательности можно использовать в экземпляре выражения XQuery. Для обращения к типам в выражениях XQuery применяется синтаксис SequenceType, описанный в спецификации XQuery.
Имя атомарного типа также можно использовать в приведение как выражение XQuery. В SQL Server экземпляр и приведение в виде выражений XQuery в SequenceTypes частично поддерживаются.
Оператор instance of
Экземпляр оператора можно использовать для определения динамического или времени выполнения значения указанного выражения. Например:
Expression instance of SequenceType[Occurrence indicator]
Обратите внимание, что оператор, Occurrence indicator
указывает instance of
кратность, количество элементов в результирующей последовательности. Если он не указан, предполагается, что количество элементов равно 1. В SQL Server поддерживается только индикатор возникновения вопросительного знака (? ). Индикатор вхождения ? указывает, что Expression
может возвращать ноль или один элемент. Если указан индикатор вхождения ? возвращает значение True, если Expression
тип соответствует указанномуSequenceType
, независимо от тогоExpression
, instance of
возвращается ли одинтон или пустая последовательность.
Если индикатор вхождения ? не указан, возвращает значение True только в том случае, sequence of
если Expression
тип соответствует Type
указанному и Expression
возвращает одноэлементный.
Обратите внимание, что индикаторы появления звездочки () и звездочки (+*) не поддерживаются в SQL Server.
В следующих примерах показано использованиеэкземпляра оператора XQuery.
Пример A
В следующем примере создается переменная типа XML и указывается запрос к нему. В выражении запроса используется оператор instance of
для определения того, соответствует ли динамический тип значения, возвращаемого первым операндом, типу второго операнда.
Следующий запрос возвращает значение True, так как значение 125 является экземпляром указанного типа xs :integer:
declare @x xml
set @x=''
select @x.query('125 instance of xs:integer')
go
Следующий запрос возвращает True, потому что значение, возвращаемое выражением /a[1], то есть первым операндом, является элементом.
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
Пример Б
В этом примере запрашиваются данные типизированного XML-столбца образца базы данных AdventureWorks. Сведения о типах предоставляет связанная с этим столбцом коллекция XML-схем.
В выражении data() возвращает типизированное значение атрибута 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.
Следующие запросы используют логическое 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
Следующий запрос выполняется для типизированного XML-столбца CatalogDescription. Сведения о типах предоставляет связанная с этим столбцом коллекция XML-схем.
Для проверки того, возвращает ли выражение element(ElementName, ElementType?)
узел с конкретным именем и типом, в операторе instance of
используется выражение /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.
Пример В
При использовании типов instance of
объединения выражение в SQL Server имеет ограничение. В частности, если тип элемента или атрибута является типом объединения, 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
Следующий запрос возвращает False, потому что тип SequenceType, указанный в выражении instance of
, не является самым старшим родительским типом фактического типа указанного выражения. То есть значение <TestElement
> целочисленного типа. а его самый старший родительский тип — xs:decimal. Однако он не указан в качестве второго операнда оператора instance of
.
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, то, если в этом запросе указать в качестве SequenceType тип xs:decimal, запрос возвратит 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
Пример Г
В этом примере сначала создайте коллекцию схем XML и используйте ее для ввода xml-переменной. Затем типизированные xml-переменные запрашиваются, чтобы проиллюстрировать функциональные instance of
возможности.
Следующая коллекция схем XML определяет простой тип, myType и элемент <root
>типа myType:
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 наследуется по ограничению от типа varchar, который определен в схеме sqltypes, в этом случае оператор 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
Пример Д
В следующем примере выражение получает одно из значений атрибута IDREFS, после чего с помощью оператора instance of
определяется, имеет ли это значение тип IDREF. В примере выполняются следующие действия.
Создает коллекцию xml-схем, в которой <
Customer
> элемент имеет атрибут типа OrderList IDREFS, аOrder
> <элемент имеет атрибут типа OrderID ID.Создает типизированные xml-переменные и назначает пример экземпляра XML.
Задается запрос, который должен быть выполнен для переменной. Выражение запроса извлекает первое значение идентификатора заказа из атрибута типа IDRERS OrderList первого <
Customer
>. Это значение имеет тип 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(ElementName, TypeName)
, тип должен быть квалифицирован с помощью вопросительного знака (?). Например, инструкцияelement(Title, xs:string?)
указывает, что элемент может иметь значение NULL. SQL Server не поддерживает обнаружение свойства xsi:nil во время выполнения с помощьюinstance of
.Если значение
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
Приведение как выражение можно использовать для преобразования значения в определенный тип данных. Например:
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
Явное использование данных() не требуется в этом запросе. Оператор cast as
неявно выполняет атомизацию входного выражения.
Функции-конструкторы
Можно использовать функции-конструкторы атомарных типов. Например, вместо использования cast as
оператора "2" cast as xs:integer?
можно использовать функцию конструктора xs:integer(), как показано в следующем примере:
declare @x xml
set @x=''
select @x.query('xs:integer("2")')
Следующий код возвращает значение xs:date, равное 2000-01-01Z:
declare @x xml
set @x=''
select @x.query('xs:date("2000-01-01Z")')
Конструкторы можно применять и при работе с пользовательскими атомарными типами. Например, если коллекция схем XML, связанная с типом данных XML, определяет простой тип, конструктор myType() можно использовать для возврата значения этого типа.
Ограничения реализации
Выражения XQuery типы, приведение и обработку не поддерживаются.
приведения, как требуется вопросительный знак (?) после атомарного типа.
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>