Поделиться через


Выражения 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>  
    

См. также

Выражения XQuery
Система типов (XQuery)