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