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

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

Иерархия типов XQuery 1.0

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

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

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

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

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

Описывает правила приведения типов языка XQuery.

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

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

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

  • Производный тип может быть приведен к примитивному типу в случае, если его примитивный тип-предок может быть приведен к целевому типу. Например, можно привести производный тип xs:integer к примитивному типу xs:string, так как примитивный тип-предок типа xs:integer — тип xs:decimal — может быть приведен к типу 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 должен представлять собой документ с одиночным элементом верхнего уровня. Если в экземпляре XML будет создано два элемента <root>, будет возвращена ошибка.

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"))

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

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

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

  • Тип decimal можно повысить до типа float, а тип float можно повысить до типа double.

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

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

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

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

При приведении одного типа к другому фактические значения трансформируются из пространства значений исходного типа в пространство значений целевого типа. Например, при приведении значения типа 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-данных