Правила приведения типов в запросах XQuery
В следующей диаграмме спецификаций функций и операторов языков W3C XQuery 1.0 и XPath 2.0 показаны встроенные типы данных. К ним относятся встроенные примитивные и встроенные производные типы.
В этом разделе описаны правила приведения типов, применяемые при приведении одного типа к другому с помощью одного из следующих методов.
- Явное приведение с помощью оператора cast as.
- Неявное приведение, выполняемое в процессе повышения типов.
Явное приведение
В следующей таблице показано разрешенное приведение встроенных примитивных типов друг к другу.
- Встроенный примитивный тип может быть приведен к другому встроенному примитивному типу на основе правил, указанных в таблице.
- Примитивный тип может быть приведен к любому производному от него типу. Например, можно привести тип 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 2005 в настоящее время типы снабжаются флагами тогда, когда ограничение типа может вызвать проблему, и при загрузке таких типов в коллекцию схем выдается предупреждение.
При приведении значения типа 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.
В SQL Server 2005, если в пространство значений целевого типа не входит ноль, приведение завершается неудачей, а результатом является пустая последовательность.
Обратите внимание, что при приведении значения к двоичному типу с плавающей запятой, например xs:float, xs:double или любому из их подтипов, точность может снизиться.
Ограничения реализации
Существуют следующие ограничения.
- Значение NaN (нечисловое) с плавающей запятой не поддерживается.