
- •Iis и xml функции sql Server
- •Поддержка xml в Microsoft sql Server 2000
- •Примеры
- •Iis и xml функции sql Server
- •Шаблоны
- •Запросы xPath
- •Замечания по разделу
- •Возможности ado 2.5 Сохранение и загрузка из файла в формате xml
- •Трансформация с помощью domDocument
- •Выдача Recordset’а в формате xml непосредственно в поток Response
- •Возможности ado 2.6
- •Использование Command для формирования xml-документа на сервере
- •Выполнение шаблона
- •Выполнение запроса xPath
- •Шаблон с агрегатными функциями
- •Формирование xml-документа на клиенте с помощью ado
- •Апдейтаграммы и xml Bulk Load
- •Апдейтаграммы
- •Добавление данных
- •Обновление данных
- •Удаление
- •Создание новой таблицы и загрузка данных
- •Загрузка иерархических документов
- •Заключение
- •Литература
- •Предисловие
- •Настройка iis
- •Содержание wsdl-файла
- •Секция types
- •Секция message
- •Секция portType
- •Формы сообщений
- •Секция binding
- •Секция service
- •Создание Web-методов
- •Тестируем Web-сервис
- •Поддержка sqlxml в .Net Framework
- •Тестовый проект
- •Цели и ограничения
- •Реализация
- •Заключение
- •Литература
- •Тип данных xml Основы
- •Метод query
- •Метод value
- •Метод exist
- •Метод modify
- •Использование xml-типа
- •Хранение xml-типа
- •Поддержка xml Schema
- •Создание схемы
- •Удаление схемы
- •Ограничения текущей реализации
- •Безопасность
- •Вложенные запросы for xml
- •Генерация xsd на лету
- •Поддержка xQuery
- •Тело запроса
- •Конструкторы узлов
- •Операторы сравнения
- •Операторы сравнения атомарных значений
- •Общие операторы сравнения
- •Операторы сравнения узлов
- •Логические операторы
- •Условные выражения
- •Flwor-выражения
- •Кванторные выражения
- •Сортировка
- •Заключение
- •Литература
Вложенные запросы for xml
Раньше нельзя было выполнять вложенные запросы, возвращающие xml. Теперь это стало возможным. Например:
select name, object_id, (select name, index_id from sys.indexes [index] where [index].object_id = object.object_id for xml auto, type ) from sys.objects object for xml auto |
Вложенный запрос возвращает тип xml, и серверу абсолютно безразлично, как он был получен. Т.е. с тем же успехом можно написать так:
declare @xml xml set @xml = '<root/>' select name, object_id, @xml from sys.objects object for xml auto |
При этом содержимое переменной @xml вставляется в результирующий XML-фрагмент (более точно: все элементы верхнего уровня XML-документа вложенного запроса копируются в результирующий фрагмент как дочерние узлы элемента, обозначающего строку выборки).
XSINIL
Теперь пустое значение можно представлять с помощью стандартного механизма, принятого в XML для обозначения значения NULL. Суть проблемы заключается в том, что в режиме for xml auto, elements поля со значением NULL просто не попадают в результирующий XML-фрагмент. Например:
select top 4 object_id, case when object_id % 2 = 0 then null else object_id end obj from sys.indexes for xml auto, elements |
Возвращает:
<sys.indexes> <object_id>133575514</object_id> </sys.indexes> <sys.indexes> <object_id>677577452</object_id> </sys.indexes> <sys.indexes> <object_id>677577452</object_id> </sys.indexes> <sys.indexes> <object_id>693577509</object_id> <obj>693577509</obj> </sys.indexes> |
Как видите, для первых трех строк элемент obj отсутствует, потому что равен NULL. Для того чтобы передать информацию о том, что он равен NULL, в XML-документ, необходимо добавить ключевое слово xsinil следующим образом:
select top 4 object_id, case when object_id % 2 = 0 then null else object_id end obj from sys.indexes for xml auto, elements xsinil |
Теперь все в порядке (изменения выделены):
<sys.indexes xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <object_id>133575514</object_id> <obj xsi:nil="1" /> </sys.indexes> <sys.indexes xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <object_id>677577452</object_id> <obj xsi:nil="1" /> </sys.indexes> <sys.indexes xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <object_id>677577452</object_id> <obj xsi:nil="1" /> </sys.indexes> <sys.indexes xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <object_id>693577509</object_id> <obj>693577509</obj> </sys.indexes> |
Генерация xsd на лету
Раньше создать схему на лету можно было только в формате XDR с помощью конструкции for xml , xmldata. Так как спецификация XRD, которая никогда не была официальным стандартом, уже давно устарела, разработчики, наконец, ввели поддержку генерации схемы в формате XSD по результатам выборки. Например, нехитрый запрос:
select top 4 name, object_id from sys.indexes for xml auto, xmlschema, elements xsinil |
возвращает следующий, довольно хитрый, результат:
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" targetNamespace="http://schemas.microsoft.com/sql/2002/types"> <xsd:simpleType name="nvarchar"> <xsd:restriction base="xsd:string"/> </xsd:simpleType> <xsd:simpleType name="int"> <xsd:restriction base="xsd:int"/> </xsd:simpleType> </xsd:schema> <xsd:schema targetNamespace="urn:schemas-microsoft-com:sql:SqlRowSet8" xmlns:schema="urn:schemas-microsoft-com:sql:SqlRowSet8" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:sqltypes="http://schemas.microsoft.com/sql/2002/types" elementFormDefault="qualified"> <xsd:import namespace="http://schemas.microsoft.com/sql/2002/types"/> <xsd:element name="sys.indexes"> <xsd:complexType> <xsd:sequence> <xsd:element name="name" nillable="1"> <xsd:simpleType> <xsd:restriction base="sqltypes:nvarchar" sqltypes:localeId="1049" sqltypes:sqlCompareOptions="IgnoreCase IgnoreKanaType IgnoreWidth"> <xsd:maxLength value="128"/> </xsd:restriction> </xsd:simpleType> </xsd:element> <xsd:element name="object_id" type="sqltypes:int" nillable="1"/> </xsd:sequence> </xsd:complexType> </xsd:element> </xsd:schema> <sys.indexes xmlns="urn:schemas-microsoft-com:sql:SqlRowSet8" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <name>pk_dtproperties</name> <object_id>133575514</object_id> </sys.indexes> <sys.indexes xmlns="urn:schemas-microsoft-com:sql:SqlRowSet8" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <name xsi:nil="1"/> <object_id>677577452</object_id> </sys.indexes> <sys.indexes xmlns="urn:schemas-microsoft-com:sql:SqlRowSet8" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <name>IX_composite</name> <object_id>677577452</object_id> </sys.indexes> <sys.indexes xmlns="urn:schemas-microsoft-com:sql:SqlRowSet8" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <name xsi:nil="1"/> <object_id>693577509</object_id> </sys.indexes> |
Вложенные запросы не могут генерировать схему. Это может делать только запрос верхнего уровня. Все вложенные XML-фрагменты такого многоуровневого запроса представляются типом xsd:anyType. Кроме этого, нельзя генерировать XSD-схему на лету в режиме explicit.
sql:variable и sql:column
Может сложиться ситуация, когда в запросе XQuery нужно получить значение поля sql-запроса или внешней переменной. Для таких целей в SQL Server-е введены две функции расширения: variable и column, которые должны находиться в неком пространстве имен с префиксом sql. Если в запросе объявляется какое-либо пространство имен с тем же префиксом sql, выше обозначенные функции становятся недоступными. Надеюсь, эту ошибку, как и бесчисленное множество других, разработчики поправят к релизу.
В функцию sql:variable передается один параметр – строковый литерал, значение которого трактуется как имя переменной простого типа во внешней области видимости. Функция возвращает скалярное значение этой переменной. Например:
declare @xml xml set @xml = ' <fam> <husband income="180">alex</husband> <wife income="161">rosa</wife> <son income="90">dima</son> </fam>'
declare @i int set @i = 150 select @xml::query('/fam/*[@income < sql:variable("@i")]') |
Здесь выбираются все дочерние элементы fam, у которых атрибут income меньше значения внешней переменной i.
Похожим образом используется функция sql:column. Она позволяет получить значение поля из внешнего запроса.
Например, следующий запрос содержит в себе XQuery-подзапрос, обращающийся к колонке id внешнего SQL-запроса.
select fam::query('<fam id = "{sql:column("id")}"> {/fam/*} </fam>') from fams |
Результат:
<fam id="1"> <husband income="180">alex</husband> <wife income="161">rosa</wife> <son income="90">dima</son> </fam> |
С помощью этой функции нельзя обращаться к колонкам XML-типа.
OPENXML
Как уже говорилось в первой части этой статьи [6], при использовании функции openxml можно было не указывать структуру и типы полей результирующей выборки, опуская ключевое слово with. В этом случае результат возвращался в так называемом edge table формате. Например,
declare @h int exec sp_xml_preparedocument @h out, '<a><b/></a>' select * from openxml(@h, '/') exec sp_xml_removedocument @h |
Возвращает:
id parentid nodetype localname prefix namespaceuri datatype prev text -- -------- -------- --------- ------ ------------ -------- ---- ---- 0 NULL 1 a NULL NULL NULL NULL NULL 2 0 1 b NULL NULL NULL NULL NULL |
Теперь можно получать доступ к внутренней информации, использующейся в процессе создания edge table, при формировании структуры результирующей выборки. Это делается с помощью атрибутов метасвойств (metaproperty attributes), которые находятся в пространстве имен urn:schemas-microsoft-com:xml-metaprop, которому назначен префикс mp. Список всех метаатрибутов я приводить не буду: достаточно взглянуть на шапку предыдущей таблицы. Вот пример их использования:
declare @h int exec sp_xml_preparedocument @h out, '<a attr="it is"><b>text1</b><b>text2</b></a>' select * from openxml(@h, '/a/b|/a') with( nodeid int '@mp:id', parentid int '@mp:parentid', nodename varchar(10) '@mp:localname', text1 varchar(100) '../@attr', text2 varchar(100) 'text()' ) exec sp_xml_removedocument @h |
Здесь выбирается три строки - два элемента b и элемент а. Вот результат:
nodeid parentid nodename text1 text2 ------ -------- -------- ----- ----- 0 NULL a NULL NULL 3 0 b it is text1 4 0 b it is text2 |