Правила приведения типов в запросах XQuery

Применимо к:SQL Server

В следующей диаграмме спецификаций функций и операторов языков W3C XQuery 1.0 и XPath 2.0 показаны встроенные типы данных. К ним относятся встроенные примитивные и встроенные производные типы.

XQuery 1.0 type hierarchy

В этом разделе описаны правила приведения типов, применяемые при приведении одного типа к другому с помощью одного из следующих методов.

  • Явное приведение, которое выполняется с помощью приведения как или функций конструктора типов (например, xs:integer("5")).

  • Неявное приведение, выполняемое в процессе повышения типов.

Явное приведение

В следующей таблице показано разрешенное приведение встроенных примитивных типов друг к другу.

Describes casting rules for XQuery.

  • Встроенный примитивный тип может быть приведен к другому встроенному примитивному типу на основе правил, указанных в таблице.

  • Примитивный тип может быть приведен к любому производному от него типу. Например, можно привести от xs:десятичного до xs:integer или от xs:десятичного до xs:long.

  • Производный тип может быть приведен к любому типу, являющемуся его предком в иерархии типов, вплоть до его встроенного примитивного базового типа. Например, можно приведения из xs:token в xs:normalizedString или в xs:string.

  • Производный тип может быть приведен к примитивному типу в случае, если его примитивный тип-предок может быть приведен к целевому типу. Например, можно привести xs:integer, производный тип к xs:string, примитивному типу, так как предок примитива xs:decimal, xs:integer может быть приведение к xs:string.

  • Производный тип может быть приведен к другому производному типу, если примитивный тип-предок исходного типа может быть приведен к примитивному типу-предку целевого типа. Например, можно приведения из xs:integer в xs:token, так как можно приведения из xs:decimal к xs:string.

  • Правила приведения определяемых пользователем типов к встроенным являются теми же, что и для встроенных типов. Например, можно определить тип myInteger, производный от типа xs:integer. Затем myInteger можно привести к xs:token, так как xs:decimal может быть приведение к xs:string.

Следующие способы приведения типов не поддерживаются.

  • Приведение к списковым типам или списковых типов к другим недопустимо. Это включает как определяемые пользователем типы списков, так и встроенные типы списков, такие как xs:IDREFS, xs:ENTITIES и xs:NMTOKENS.

  • Приведение к xs:QName не поддерживается.

  • xs:NOTATION и полностью упорядоченные подтипы длительности, xdt:yearMonthDuration и xdt:dayTimeDuration, не поддерживаются. В результате приведение к этим типам или этих типов к другим не поддерживается.

В следующих примерах показано явное приведение типов.

Пример A

В следующем примере запрашивается переменная XML-типа. Запрос возвращает последовательность значения простого типа, типизированного как xs:string.

declare @x xml  
set @x = '<e>1</e><e>2</e>'  
select @x.query('/e[1] cast as xs:string?')  
go  

Пример Б

В следующем примере запрашивается типизированная переменная типа XML. Сначала создается коллекция XML-схем. Затем эта коллекция используется для создания типизированной переменной типа XML. В схеме содержатся сведения о типизации для экземпляра XML, назначенного переменной. После этого запросы направляются к данной переменной.

create xml schema collection myCollection as N'  
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">  
      <xs:element name="root">  
            <xs:complexType>  
                  <xs:sequence>  
                        <xs:element name="A" type="xs:string"/>  
                        <xs:element name="B" type="xs:string"/>  
                        <xs:element name="C" type="xs:string"/>  
                  </xs:sequence>  
            </xs:complexType>  
      </xs:element>  
</xs:schema>'  
go  

Следующий запрос возвращает статическую ошибку, так как вы не знаете, сколько элементов верхнего уровня <root> находятся в экземпляре документа.

declare @x xml(myCollection)  
set @x = '<root><A>1</A><B>2</B><C>3</C></root>  
          <root><A>4</A><B>5</B><C>6</baz></C>'  
select @x.query('/root/A cast as xs:string?')  
go  

При указании однотонного <root> элемента в выражении запрос завершается успешно. Запрос возвращает последовательность значения простого типа, типизированного как xs:string.

declare @x xml(myCollection)  
set @x = '<root><A>1</A><B>2</B><C>3</C></root>  
              <root><A>4</A><B>5</B><C>6</C></root>'  
select @x.query('/root[1]/A cast as xs:string?')  
go  

В следующем примере переменная XML-типа содержит ключевое слово document, указывающее на коллекцию XML-схем. Это слово указывает, что экземпляр XML должен представлять собой документ с одиночным элементом верхнего уровня. Если вы создаете два <root> элемента в экземпляре XML, он вернет ошибку.

declare @x xml(document myCollection)  
set @x = '<root><A>1</A><B>2</B><C>3</C></root>  
              <root><A>4</A><B>5</B><C>6</C></root>'  
go  

Можно изменить экземпляр таким образом, чтобы он содержал только один элемент верхнего уровня, и запрос будет работать. Запрос вновь возвращает последовательность значения простого типа, типизированного как xs:string.

declare @x xml(document myCollection)  
set @x = '<root><A>1</A><B>2</B><C>3</C></root>'  
select @x.query('/root/A cast as xs:string?')  
go  

Неявное приведение

Неявное приведение разрешено только для числовых типов и нетипизированных атомарных типов. Например, следующая функция min() возвращает минимум двух значений:

min(xs:integer("1"), xs:double("1.1"))  

В этом примере два значения, передаваемые в функцию XQuery min(), имеют разные типы. Таким образом, неявное преобразование выполняется, когда целочисленный тип увеличивается до двойного и сравниваются два двойных значения.

Повышение типов, описанное в данном примере, выполняется по следующим правилам.

  • Встроенный производный числовой тип можно повышать до его базового типа. Например, целое число может быть повышено до десятичного.

  • Десятичное значение может быть повышено до плавающего, а плавающее значение может быть повышено до двойного.

Так как неявное приведение допустимо только для числовых типов, следующие операции недопустимы.

  • Неявное приведение строковых типов недопустимо. Например, если ожидается два типа строк, и вы передаете строку и маркер, не происходит неявное приведение и возвращается ошибка.

  • Неявное приведение числовых типов к строковым недопустимо. Например, в случае передачи значения целого типа функции, принимающей параметр строкового типа, неявное приведение выполняться не будет, и будет возвращена ошибка.

Приведение значений

При приведении одного типа к другому фактические значения трансформируются из пространства значений исходного типа в пространство значений целевого типа. Например, при приведении значения типа xs:decimal к типу xs:double значение decimal будет преобразовано в значение double.

Ниже приведены некоторые правила преобразования.

Приведение значения типа string или untypedAtomic к другому типу

Значение, которое приводится к типу string или untypedAtomic, преобразуется таким же образом, что и при проверке значения на основе правил целевого типа. Сюда входят правила сопоставления с ожидаемым шаблоном и обработки пробелов. Например, следующая операция завершится успехом, а результатом ее будет значение типа double 1.1e0:

xs:double("1.1")

При приведении типов string или untypedAtomic к двоичным типам, например xs:base64Binary или xs:hexBinary, входные значения должны быть закодированы по алгоритму base64 или hex соответственно.

Приведение значения к типу string или untypedAtomic

При приведении значения к типу string или untypedAtomic оно будет преобразовано в свое каноническое лексическое представление в языке XQuery. Конкретно это означает, что значение, которое при вводе укладывалось в заданный шаблон или другое ограничение, не будет представлено в соответствии с данным ограничением. Чтобы сообщить пользователям об этом, SQL Server помечает типы, в которых ограничение типа может быть проблемой, предоставив предупреждение при загрузке этих типов в коллекцию схем.

При приведении значения типа xs:float к типу xs:double или какому-либо из его подтипов, к типу string или untypedAtomic, значение будет представлено в экспоненциальной записи. Это производится только в случае, если абсолютное значение данного значения меньше 1.0E-6 или же больше или равно 1.0E6. Таким образом, 0 сериализуется в экспоненциальном представлении в форме 0.0E0.

Например, операция xs:string(1.11e1) возвращает строковое значение "11.1", в то время как операция xs:string(-0.00000000002e0) возвращает строковое значение "-2.0E-11".

При приведении двоичных типов, например xs:base64Binary или xs:hexBinary, к типу string или untypedAtomic, двоичные значения будут представлены в закодированной форме по алгоритму base64 или hex соответственно.

Приведение значения к числовому типу

При приведении значения одного числового типа к значению другого числового типа оно отображается из одного пространства значений в другое без строковой сериализации. Если значение не удовлетворяет ограничениям целевого типа, применяются следующие правила.

  • Если исходное значение уже является числовым, а целевой тип — xs:float либо его подтип, для которого допустимы значения -INF и INF, и приведение исходного числового значения к целевому типу вызовет переполнение, значение сопоставляется с INF, если оно положительное, и с -INF — если отрицательное. Если для целевого типа недопустимы значения INF и -INF и может произойти переполнение, приведение завершается неудачей и SQL Server выдает в качестве результата пустую последовательность.

  • Если исходное значение уже является числовым, а целевой тип — числовой и его диапазон приемлемых значений включает 0, -0e0 или 0e0 и приведение исходного числового значения к целевому типу вызовет потерю точности, сопоставление значения выполняется следующим образом.

    • Для десятичного целевого типа значению сопоставляется 0.

    • В случае потери точности отрицательного значения ему сопоставляется -0e0.

    • В случае потери точности положительного значения для целевого типа с плавающей точкой или с двойной точностью ему сопоставляется 0e0.

    Если в пространство значений целевого типа не входит ноль, приведение завершается неудачей, а результатом является пустая последовательность.

    Обратите внимание, что при приведении значения к двоичному типу с плавающей запятой, например xs:float, xs:double или любому из их подтипов, точность может снизиться.

Ограничения реализации

Существуют следующие ограничения:

  • Значение NaN (нечисловое) с плавающей запятой не поддерживается.

  • На значения, доступные для приведения, накладываются ограничения реализации целевых типов. Например, нельзя привести строку даты с отрицательным годом к xs:date. Если значение предоставляется во время выполнения, результатом такого приведения будет пустая последовательность (а не ошибка времени выполнения).

См. также

Определение сериализации данных XML