Типы данных XPath (SQLXML 4.0)

Применимо к:база данных SQL ServerAzure SQL

Microsoft SQL Server, XPath и XML Schema (XSD) имеют очень разные типы данных. Например, XPath не имеет целочисленных или датных типов данных, но SQL Server и XSD имеют много. XSD использует точность наносекунд для значений времени, а SQL Server — не более 1/300 секунд. Поэтому не всегда возможно сопоставить один тип другому. Дополнительные сведения о сопоставлении типов данных SQL Server с типами данных XSD см. в разделах Приведение типов данных и заметка sql:datatype (SQLXML 4.0).

XPath имеет три типа данных: string, number и boolean. Типом данных number всегда является стандарт IEEE 754 двойной точности с плавающей запятой. Тип данных SQL Server float(53) ближе всего к числу XPath. Однако float(53) не совсем ieee 754. В частности, этот тип не содержит ни значения NaN (не число), ни значения бесконечности. Попытка преобразовать нечисловую строку в число и попытка деления на ноль приводит к ошибке.

Преобразования в XPath

При использовании запроса XPath, например, OrderDetail[@UnitPrice > "10.0"], явные и неявные преобразования типов данных могут различными неочевидными способами изменить значение запроса. Поэтому важно знать, как реализована система типов данных в XPath. Спецификацию языка XPath, XPath версии 1.0, предлагаемую рекомендацию W3C от 8 октября 1999 года, можно найти на веб-сайте W3C по адресу http://www.w3.org/TR/1999/PR-xpath-19991008.html.

Операторы XPath делятся на четыре категории:

  • Логические операторы (и, или)

  • Реляционные операторы (<, >, <=, >=)

  • Операторы равенства (=, !=)

  • Арифметические операторы (+, -, *, div, mod)

Операторы разных категорий по-разному преобразуют операнды. При необходимости операторы XPath неявно преобразуют операнды. Арифметические операторы преобразуют свои операнды в число и приводят к числовой величине. Логические операторы преобразуют свои операнды в логические и приводят к логическому значению. Результатом выполнения реляционных операторов и операторов равенства является логическое значение. Однако правила преобразования, которыми пользуются операторы, зависят от первоначальных типов операндов, как показано в таблице.

Операнд Реляционный оператор Оператор равенства
Оба операнда представляют собой наборы узлов. ЗНАЧЕНИЕ TRUE, если и только если есть узел в одном наборе и узел во втором наборе, поэтому сравнение их строковых значений равно TRUE. То же.
Один из них является набором узлов, другой — строкой. ЗНАЧЕНИЕ TRUE, только если в наборе узлов есть узел, который при преобразовании в число сравнивается со строкой , преобразованной в число , имеет значение TRUE. ЗНАЧЕНИЕ TRUE, если в наборе узлов есть узел и только в том случае, если при преобразовании в строку его сравнение со строкой имеет значение TRUE.
Один из них является набором узлов, другой — числом. ЗНАЧЕНИЕ TRUE, если в наборе узлов есть узел и только в том случае, если при преобразовании в число его сравнение с числом имеет значение TRUE. То же.
Один из них — набор узлов, другой — логический. ЗНАЧЕНИЕ TRUE, только если в наборе узлов есть узел, который при преобразовании в логическое значение, а затем в число, сравнение его с логическим значением, преобразованным в число , имеет значение TRUE. ЗНАЧЕНИЕ TRUE, только если в наборе узлов есть узел, который при преобразовании в логическое значение сравнивается с логическим значением TRUE.
Ни один из них не представляет собой набор узлов. Преобразуйте оба операнда в число , а затем сравните. Преобразует оба операнда к одному типу, а затем сравнивает их. Преобразуйте в логическое значение, если одно из этих значений является логическим, число , если любое из этих значений является числом; В противном случае преобразуйте в строку.

Примечание

Так как реляционные операторы XPath всегда преобразуют операнды в число, сравнение строк невозможно. Для сравнения дат SQL Server 2000 предлагает такой вариант спецификации XPath: когда реляционный оператор сравнивает строку со строкой, набор узлов со строкой или набор узлов со строковым значением с набором узлов со строковым значением, выполняется сравнение строк (а не сравнение чисел).

Преобразования наборов узлов

Преобразования наборов узлов не всегда интуитивно понятны. Набор узлов преобразуется в строку , принимая строковое значение только первого узла в наборе. Набор узлов преобразуется в число путем преобразования его в строку, а затем преобразования строки в число. Набор узлов преобразуется в логический путем проверки его существования.

Примечание

SQL Server не выполняет позиционный выбор для наборов узлов: например, запрос Customer[3] XPath означает третьего клиента; этот тип позиционного выбора не поддерживается в SQL Server. Поэтому преобразования типа "набор узлов в строку " или "набор узлов в число ", описанные в спецификации XPath, не реализуются. SQL Server использует семантику "любой", где спецификация XPath задает семантику "первый". Например, на основе спецификации W3C XPath запрос Order[OrderDetail/@UnitPrice > 10.0] XPath выбирает эти заказы с первым OrderDetail , у которого значение UnitPrice больше 10.0. В SQL Server этот запрос XPath выбирает эти заказы с любой orderDetail, у которого значение UnitPrice больше 10.0.

Преобразование в логическое приводит к созданию проверки существования; Поэтому запрос Products[@Discontinued=true()] XPath эквивалентен выражению SQL "Products.Discontinued не null", а не выражению SQL "Products.Discontinued = 1". Чтобы сделать запрос эквивалентным последнему выражению SQL, сначала преобразуйте набор узлов в тип, отличный от типа boolean , например number. Например, Products[number(@Discontinued) = true()].

Большинство операторов реализовано так, что они возвращают TRUE, если их результат равен TRUE хотя бы для одного (любого) узла набора, поэтому они возвращают FALSE, если набор узлов пуст. Таким образом, если набор узлов A пуст, оба оператора A = B и A != B вернут FALSE, а not(A=B) и not(A!=B) — TRUE.

Как правило, атрибут или элемент, сопоставляющийся со столбцом, существует, если значение этого столбца в базе данных не равно NULL. Элементы, сопоставляемые со строками, существуют, если есть хотя бы один из их дочерних элементов.

Примечание

Элементы с заметками is-constant всегда существуют. Следовательно, предикаты XPath нельзя использовать для элементов is-constant .

При преобразовании набора узлов в строку или число его тип XDR (если таковой имеется) проверяется в схеме с заметками, и этот тип используется для определения требуемого преобразования.

Сопоставление типов данных XDR типам данных XPath

Тип данных XPath узла является производным от типа данных XDR в схеме, как показано в следующей таблице (узел EmployeeID используется для иллюстрации).

Тип данных XDR Эквивалентный

тип данных XPath
Использованное преобразование SQL Server
Nonebin.base64bin.hex Н/Д NoneEmployeeID
Логическое Логическое CONVERT(bit, EmployeeID)
number, int, float,i1, i2, i4, i8,r4, r8ui1, ui2, ui4, ui8 number CONVERT(float(53), EmployeeID)
id, idref, idrefsentity, entities, enumerationnotation, nmtoken, nmtokens, chardate, Timedate, Time.tz, string, uri, uuid строка CONVERT(nvarchar(4000), EmployeeID, 126)
fixed14.4 н/д (в XPath нет типа данных, эквивалентного типу fixed14.4 XDR) CONVERT(money, EmployeeID)
Дата строка LEFT(CONVERT(nvarchar(4000), EmployeeID, 126), 10)
time

time.tz
строка SUBSTRING(CONVERT(nvarchar(4000), EmployeeID, 126), 1 + CHARINDEX(N'T', CONVERT(nvarchar(4000), EmployeeID, 126)), 24)

Преобразования даты и времени предназначены для работы независимо от того, хранится ли значение в базе данных с использованием типа данных SQL Server datetime или строки. Обратите внимание, что тип данных SQL Server datetime не использует часовой пояс и имеет меньшую точность, чем тип данных времени XML. Чтобы включить тип данных часового пояса или дополнительную точность, сохраните данные в SQL Server с помощью строкового типа.

При преобразовании узла из типа данных XDR в тип данных XPath иногда требуются дополнительные преобразования (из одного типа XPath в другой тип XPath). В качестве примера рассмотрим следующий запрос XPath:

(@m + 3) = 4  

Если @m имеет тип данных XDR fixed14.4 , преобразование типа данных XDR в тип данных XPath выполняется с помощью следующих средств:

CONVERT(money, m)  

В этом преобразовании узел m преобразуется из fixed14.4 в money. Однако для прибавления 3 требуется дополнительное преобразование:

CONVERT(float(CONVERT(money, m))  

Выражение XPath вычисляется следующим образом:

CONVERT(float(CONVERT(money, m)) + CONVERT(float(53), 3) = CONVERT(float(53), 3)  

Как показано в следующей таблице, это то же самое преобразование, которое применялось для других выражений XPath (например, литералов или составных выражений).

Х неизвестен X — это строка X — число X является логическим
string(X) CONVERT (nvarchar(4000), X, 126) - CONVERT (nvarchar(4000), X, 126) CASE WHEN X THEN N'true' ELSE N'false' END
number(X) CONVERT (float(53), X) CONVERT (float(53), X) - CASE WHEN X THEN 1 ELSE 0 END
boolean(X) - LEN(X) > 0 X != 0 -

Примеры

A. Преобразование типа данных в запросе XPath

В следующем запросе XPath, указанном к схеме XSD с заметками, запрос выбирает все узлы Employee со значением атрибута EmployeeID E-1, где "E-" — это префикс, указанный с помощью заметки sql:id-prefix .

Employee[@EmployeeID="E-1"]

Предикат в запросе эквивалентен следующему выражению SQL:

N'E-' + CONVERT(nvarchar(4000), Employees.EmployeeID, 126) = N'E-1'

Так как EmployeeID является одним из значений типа данных id (idref, idrefs, nmtoken, nmtokens и т. д.) в схеме XSD, EmployeeID преобразуется в строковый тип данных XPath с помощью правил преобразования, описанных выше.

CONVERT(nvarchar(4000), Employees.EmployeeID, 126)

К строке добавляется префикс «E-», а результат затем сравнивается с N'E-1'.

Б. Несколько преобразований типов данных в запросе XPath

Рассмотрим этот запрос XPath, указанный для схемы XSD с заметками: OrderDetail[@UnitPrice * @OrderQty > 98]

Этот запрос XPath возвращает все <элементы OrderDetail> , удовлетворяющие предикату @UnitPrice * @OrderQty > 98. Если в схеме с заметками UnitPrice используется тип данных fixed14.4 , то этот предикат эквивалентен выражению SQL:

CONVERT(float(53), CONVERT(money, OrderDetail.UnitPrice)) * CONVERT(float(53), OrderDetail.OrderQty) > CONVERT(float(53), 98)

В ходе преобразований значений в запросе XPath сначала тип данных XDR преобразуется в тип данных XPath. Так как тип данных XSD UnitPrice имеет значение fixed14.4, как описано в предыдущей таблице, это первое используемое преобразование:

CONVERT(money, OrderDetail.UnitPrice))   

Так как арифметические операторы преобразуют свои операнды в числовой тип данных XPath, применяется второе преобразование (из одного типа данных XPath в другой тип данных XPath), в котором значение преобразуется в тип данных float(53) (float(53) близко к типу данных XPath number :

CONVERT(float(53), CONVERT(money, OrderDetail.UnitPrice))   

Если атрибут OrderQty не имеет типа данных XSD, OrderQty преобразуется в числовой тип данных XPath в рамках одного преобразования:

CONVERT(float(53), OrderDetail.OrderQty)  

Аналогичным образом значение 98 преобразуется в числовой тип данных XPath:

CONVERT(float(53), 98)  

Примечание

Если тип данных XSD, используемый в схеме, несовместим с базовым типом данных SQL Server в базе данных или если выполняется невозможное преобразование типа данных XPath, SQL Server может вернуть ошибку. Например, если атрибут EmployeeID помечен заметкой id-prefix , XPath Employee[@EmployeeID=1] создает ошибку, так как EmployeeID содержит заметку id-prefix и не может быть преобразована в число.