17.1.23

Поддержка XML в Microsoft SQL Server 2005

По материалам статьи XML Support in Microsoft SQL Server 2005



Перевод Виталия Степаненко

В этой статье рассматривается добавленная в SQL Server 2005 поддержка XML. В статье также показано, как эта поддержка интегрируется с программной поддержкой со стороны клиента в .NET Framework V2.0 и в родном коде, как OLEDB и SQLXML.


    Введение

    Расширенный язык разметки (eXtensible Markup Language, XML) широко распространен как платформо-независимый формат представления данных. Он полезен для обмена информацией между различными слабосвязанными системами, как в приложениях business-to-business (B2B), так и в других ситуациях. Обмен данными был главным двигателем развития технологий XML.

    XML все больше используется в приложениях уровня предприятия для моделирования частично структурированных и неструктурированных данных. Одно из таких приложений - это управление документами. Документы, такие, как e-mail, являются изначально частично структурированными. Если документы хранятся внутри сервера базы данных в виде XML, то достаточно мощные приложения могут быть разработаны для получения документов, основанные на содержимом документов, объединении документов, и запросах на получение части содержимого документа, как, например, поиск главы документа с заголовком, содержащим слово "background". Такие сценарии становятся все более возможными с ростом количества приложений, которые генерируют и потребляют XML. Например, система Microsoft Office 2003 позволяет пользователям создавать документы Word, Excel, Visio и Infopath в виде XML.


    Почему для данных XML используются реляционные базы данных?

    • Хранение данных XML в реляционной базе данных имеет свои преимущества при управлении данными и обработке запросов. SQL Server обеспечивает большие возможности для выполнения запросов к реляционным данным и изменения этих данных, которые были расширены для выполнения запросов по данным XML и их изменения. Это позволяет увеличить отдачу от инвестиций, как, например, в областях оптимизации затрат ресурсов и хранилищ данных. Например, методы индексирования в реляционной базе данных хорошо известны, и они были расширены для индексирования данных XML так, чтобы запросы могли быть оптимизированы с учетом затрат ресурсов.

    • Данные XML могут взаимодействовать с существующими реляционными данными и приложениями SQL так, чтобы XML мог быть добавлен в систему при возникновении новых потребностей без серьезного изменения существующих приложений. Сервер базы данных также обеспечивает административную функциональность для управления данными XML (например, резервное копирование, восстановление и репликация).

    • Эти возможности породили потребность в поддержке встроенного XML в SQL Server 2005 для отражения увеличивающегося использования XML. Разработка приложений уровня предприятия сильно выиграет от поддержки XML в SQL Server 2005.

    Следующие главы дают обзор поддержки XML в SQL Server 2000 и 2005, описывают некоторые сценарии использования XML и углубляются в детали использования XML на стороне сервера и клиента.


    Поддержка XML в SQL Server 2000

    Эта глава предоставляет краткий обзор поддержки XML в SQL Server 2000 и в последующих сетевых релизах платформы программирования SQLXML на клиентской стороне, что обеспечивает широкую поддержку конвертации реляционных данных в XML, и наоборот.


    Поддержка XML на стороне сервера

    На сервере данные XML могут быть сгенерированы из таблиц и результатов запросов, используя выражение FOR XML в команде SELECT. Это идеально подходит для обмена данными и для приложений Web-сервисов. Обратной операцией для FOR XML является функция генератора реляционного набора строк OpenXML; она заносит значения из данных XML в столбцы набора строк, используя выражения XPath 1.0. OpenXML используется приложениями, которые заносят входные данные XML в таблицы или выполняют запросы, используя T-SQL.


    Поддержка XML на стороне клиента

    Поддержка программирования на стороне клиента для SQL Server 2000 относится к SQLXML. Центральное место этой технологии - представление XML, которое является двусторонней конвертацией схемы XML в реляционные таблицы. SQL Server 2000 поддерживает только конвертацию схем XDR, хотя поддержка XSD была добавлена в более поздние web-релизы. Представление XML позволяет выполнять запросы, используя подмножество XPath 1.0, где конвертация используется для перевода выражений пути в запросы SQL на таблицах, и где результаты запроса вставляются в результат XML.

    SQLXML также позволяет создавать шаблоны XML, которые позволяют создавать документ XML с динамическими секциями. В документ XML вы можете встраивать запросы FOR XML и/или выражения XPath 1.0 при помощи запросов конвертации. Когда выполняется шаблон XML, блок запроса заменяется результатом этого запроса. Т.е. Вы можете создавать документы XML со статическим содержанием и с динамическим содержанием, управляемым данными.

    В SQL Server 2000 есть два пути доступа к функциональности SQLXML:

    • SQLXMLOLEDB Provider - провайдер SQLXMLOLEDB, это провайдер OLE DB, который обеспечивает функциональность Microsoft SQLXML через ADO.

    • HTTP Access - функциональность SQLXML в SQL Server 2000 может также быть достигнута через HTTP, используя фильтр SQLXML ISAPI. Используя инструмент конфигурации, вы можете настроить веб-сайт на прием входящих запросов на выполнение шаблонов XML и команд FOR XML и XPath 1.0 с помощью представлений XML через HTTP.


    Ограничения в поддержке XML

    Серверная и клиентская платформы программирования обеспечивают широкую поддержку для генерации и потребления данных XML, основанных на конвертации между табличными данными и данными XML. Это позволяет хорошо управлять структурированными данными XML. В SQLXML язык запросов является подмножеством XPath 1.0 и имеет некоторые ограничения. Например, не поддерживается descendant-or-self axis (//). Следовательно, существуют ограничения при разработке определенных решений. Например, может не сохраниться порядок документа XML, что так критично для таких приложений, как приложения управления документами. Более того, не поддерживаются рекурсивные схемы XML. Несмотря на эти ограничения, функциональность клиентского SQLXML и серверного XML широко используется при разработке приложений. SQL Server 2005 устраняет многие из этих ограничений, расширяет обмен между реляционными данными и данными XML и обеспечивает поддержку встроенного XML.


    Обзор поддержки XML в SQL Server 2005

    Эта глава предоставляет обзор поддержки XML, добавленной в SQL Server 2005, которая дополняется поддержкой XML в .NET Framework V2.0 и клиентским доступом к встроенному XML через OLE DB.


    Тип данных XML

    Модель данных XML имеет такие характеристики, которые затрудняют, если вообще не делают невозможным процесс ее конвертации в реляционную модель данных. Данные XML имеют иерархическую структуру, которая может быть рекурсивной; реляционные базы данных обеспечивают слабую поддержку для иерархических данных (в виде внешних ключей). Порядок документа является одним из основных свойств XML и должен быть сохранен в результате запроса. Это контрастирует с реляционными данными, которые неупорядочены, и их порядок указывается с помощью дополнительных столбцов. Получение результата выполнения запроса достаточно затратно для реальных схем XML, которые распределяют данные XML по большому количеству таблиц.

    В SQL Server 2005 появился встроенный тип данных - XML. Пользователь может создавать таблицу с одним или более столбцом типа XML помимо столбцов с реляционными данными; также разрешены переменные и параметры типа XML. Значения XML хранятся во внутреннем формате как большие бинарные объекты (BLOB) для лучшей поддержки характеристик модели XML, таких, как порядок документа и рекурсивные структуры.

    SQL Server 2005 обеспечивает набор схем XML в качестве средства по управлению схемами W3C XML как метаданными. Тип данных XML может быть сопоставлен с набором схемы XML, чтобы наложить ограничения на экземпляры XML. Когда данные типа XML сопоставляются с набором схем XML, они называются типизированными данными XML; иначе они называются нетипизированными данными XML. И типизированные, и нетипизированные данные XML в одной структуре, модель данных XML защищена, и обработка запроса использует семантику XML. Для этого в значительной степени используется имеющаяся реляционная инфраструктура. Она обеспечивает взаимодействие между реляционными данными и данными XML, давая возможность для более широкого использования XML.


    Запрос данных XML и модификация данных

    Экземпляры XML могут быть получены с помощью команды SELECT языка T-SQL. Пять встроенных методов на типе данных XML обеспечивают выполнение запросов и изменение экземпляров XML.

    Методы типа данных XML поддерживают XQuery, который является стандартом языка W3C и включает язык навигации XPath 2.0. Язык также доступен для изменения данных XML, например, для добавления или удаления поддеревьев и обновления скалярных значений. Вместе с большим набором функций, встроенный XQuery и языки изменения данных обеспечивают богатую поддержку управления данными XML.

    Система типов XQuery соответствует типам схем XML у W3C. Большинство типов SQL совместимы с системой типов XQuery (например, десятичный тип). Несколько типов (например, xs:duration) хранятся во внутреннем формате и они соответственно интерпретируются, чтобы быть совместимыми с системой типов XQuery.

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


    Индексирование XML

    При выполнении запроса каждый экземпляр XML обрабатывается во время работы; это может являться достаточно затратным, если значение XML имеет больший размер или когда запрос возращает большое количество строк из таблицы. Для ускорения запросов создан механизм индексирования столбцов XML.

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

    Вторичные индексы XML могут быть созданы по столбцу XML для ускорения различных классов типичных запросов: индекс PATH для основанных на пути запросов, индекс PROPERTY для сценариев свойств и индекс VALUE для основанных на значениях запросов.


    Обработка схем XML

    Столбцы, переменные и параметры XML могут быть типизированы в соответствии с набором схем XML, которые могут быть связаны (например, используя <xs:import>) или не связаны друг с другом. Каждый типизированный экземпляр XML устанавливает пространство имен из набора схем XML, относящихся к нему. Движок базы данных проверяет экземпляр в соответствии со схемой XML во время изменения данных.

    Информация схемы XML используется при хранении и оптимизации запросов. Типизированные экземпляры XML содержат типизированные значения во внутреннем, двоичном представлении, как и в индексах XML. Это обеспечивает эффективную обработку типизированных данных XML.


    Интеграция реляционных данных и данных XML

    Пользователи могут хранить и реляционные данные, и данные XML в одной и той же базе данных. Т.е. движок базы данных знает, как работать с моделью данных XML в добавление к работе с моделью реляционных данных. Реляционные данные и приложения SQL продолжают работать правильно при их обновлении до SQL Server 2005. Данные XML, находящиеся в файлах и в столбцах text или image, могут быть перемещены в столбцы типа XML на сервере. Столбец XML может быть проиндексирован, запрошен и изменен с использованием методов типа данных XML.

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

    Структурированные данные должны храниться в таблицах и реляционных столбцах. Тип данных XML - это подходящий выбор для частично структурированных данных и данных с разметкой XML, когда приложение должно выполнять запросы по этим данным и их изменение.


    Улучшения в FOR XML и OpenXML

    Существующая функциональность FOR XML была улучшена несколькими путями. Теперь можно работать с экземплярами данных XML и с другими новыми типами SQL, например, с [n]varchar(max).

    Новая директива TYPE генерирует экземпляр типа данных XML, который может быть присвоен столбцу, переменной или параметру XML, или запрошен с использованием методов типа данных XML. Это позволяет вызывать команды SELECT ... FOR XML TYPE одну из другой.

    Режим PATH позволяет пользователям определять путь в дереве XML, где должно находиться значение столбца, что вместе с вышеупомянутой вложенностью команд является более удобным, чем FOR XML EXPLICIT.

    Директива XSINIL, использующаяся вместе с ELEMENTS, конвертирует NULL в элемент с атрибутом xsi:nil="true". Также, новая директива ROOT позволяет определить корневой узел во всех режимах FOR XML. Новая директива XMLSCHEMA генерирует внутреннюю схему XSD.

    Функциональные улучшения OpenXML состоят из использования типа данных XML в sp_preparedocument и генерирования столбцов с типом XML и другими новыми типами SQL в результирующем наборе данных.


    Клиентский доступ к типу данных XML

    Клиенты могут получать доступ к данным XML на сервере несколькими путями. Встроенный клиентский доступ к SQL, использующий ODBC и OLE DB, передает тип данных XML как строку Unicode. OLE DB также обеспечивает доступ ISequentialStream к данным XML для передачи данных Unicode.

    Управляемый доступ с помощью ADO.NET в .NET Framework V2.0 передает данные XML как новый класс SqlXml. Он поддерживает метод CreateReader(), который возвращает экземпляр XmlReader для чтения возвращенного XML. Также DataSet может загружать экземпляры типа XML в столбцы на среднем уровне, которые могут быть отредактированы, как XML документ, и сохранены в SQL Server. Оба этих метода позволяют запросам SQL быть выполненными на сервере для получения столбцов XML для дальнейшей работы с ними на среднем уровне.

    SOAP, который имеет прямой доступ к HTTP в SQL Server 2005, может быть использован для выполнения запросов, получения и изменения данных XML.

    И встроенные, и управляемые клиентские технологии обеспечивают новые интерфейсы для получения набора схем XML, которые определяют тип столбца XML.


    Поддержка XML при помощи XQuery на стороне клиента

    В дополнение к использованию ADO.NET для получения таблиц в реляционный DataSet, Вы можете напрямую загружать реляционные данные в документ XML на среднем уровне, используя класс XQueryCommand. Этот класс обеспечивает обработку XQuery на среднем уровне с возможностью встраивания команд T-SQL как части языка XQuery. В этом случае вы можете запрашивать как локальные файлы XML, так и получать данные из SQL Server напрямую из таблицы или через хранимую процедуру базы данных, и загружать их в документ XML на среднем уровне. Это значительно упрощает запросы в SQL Server, выдает результат запроса в специфическом формате XML, и передает его бизнес-партнеру без необходимости загрузки данных в DataSet для выполнения изменений над данными.


    Мотивация для хранения XML

    Данные в виде XML становятся все более распространенными. Они могут представлять данные пользователя с описывающими их схемами XML или без них. И данные XML, и схемы XML должны использоваться вместе. Схемы XML для реальных приложений часто сложны, и конвертация этих схем XML в таблицы и столбцы -сложная задача. Осуществление такой конвертации в то время, когда изменяются схемы XML или добавляются новые, становится проблематичным. Довольно часто данные XML хранятся в файловой системе или в текстовом столбце на сервере базы данных. Текстовые столбцы имеют такие преимущества управления данными, как репликация и резервное копирование/восстановление, но не поддерживают запросы, основанные на структуре данных XML. С встроенной поддержкой XML разработка приложений, использующих XML, становится быстрее.


    Управление свойствами пользователем

    Некоторые приложения, такие, как приложения с пользовательским интерфейсом, позволяют пользователям выбирать из фиксированного набора свойств. Другие позволяют пользователям определять собственные, необходимые им свойства. Такими пользовательскими свойствами можно управлять, если они хранятся в формате XML. Приложения могут поддерживать не только скалярные свойства:

    • могут поддерживаться свойства объектов с множеством значений, такие, как множество номеров телефонов;

    • также могут поддерживаться сложные свойства, например, свойство автора документа может являться контактной информацией автора;

    • объектные свойства могут храниться в столбце типа XML и индексироваться для эффективной обработки запроса.


    Обмен данными

    XML позволяет осуществлять платформо-независимый обмен данными между приложениями. Такие данные могут быть смоделированы как сообщения с разметкой XML. Вместо постоянного создания и удаления сообщений XML, разумнее хранить сообщения в формате XML. Это хорошо сочетается с требованиями обмена данными. Приходящее сообщение XML содержит текущее состояние. Каждое сообщение обрабатывается, изменения записываются в содержимое XML, и данные XML передаются дальше. Сообщения могут быть разных типов или даже могут быть только частично структурированными, иметь разные схемы XML, так что их конвертация в таблицы не всегда является простой задачей.

    Стандарты, основанные на XML, появляются для различных вертикальных доменов, такие, как финансовые и географические данные. Эти стандарты описывают структуру данных, зависящую от того, какие именно данные могут быть запрошены и обновлены. Довольно часто сами данные хранятся в двоичной форме, в то время как данные XML хранят метаданные об этих данных.

    Приведем простой пример: чтобы передать таблицу входных параметров в хранимую процедуру или функцию, приложение конвертирует данные в XML и передает их как параметр типа XML. Внутри хранимой процедуры или функции из параметра XML вновь создается набор строк.


    Управление документами

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

    Документы, такие, как e-mail, только частично структурированы по своей сути. Документы с разметкой XML легче создавать, например, с помощью Office 2003. Эти документы XML могут храниться в столбцах XML, индексироваться, запрашиваться и обновляться. Таким образом, разработчики могут делать больше со встроенной поддержкой XML.


    Обработка XML на стороне сервера в SQL Server 2005

    В SQL Server 2005 Вы можете хранить в одной базе данных и реляционные данные, и данные XML.


    Тип данных XML

    Вы можете создать таблицу со столбцом XML, используя обычную команду CREATE TABLE. Столбец XML может быть проиндексирован особым образом.


    Нетипизированный XML

    Тип данных XML в SQL Server 2005 соответствует стандарту ISO SQL-2003 типа данных XML. Поэтому он может хранить не только хорошо структурированные документы XML 1.0, но также и так называемые фрагменты контента XML с текстовыми узлами и произвольным количеством элементов высокого уровня. При этом выполняются проверки на структурированность данных, что не требует привязки данных XML к схемам XML, и плохо структурированные данные не принимаются.

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

    Пример: столбец с нетипизированным XML в таблице

    Следующая команда создает таблицу "docs" с первичным ключом типа integer "pk" и столбцом с нетипизированным XML "xCol":

    
    CREATE TABLE docs (pk INT PRIMARY KEY, xCol XML not null)
    

    Таблица может быть создана с более чем одним XML или реляционным столбцом с наличием или без наличия первичного ключа.


    Типизированный XML

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

    Типизированные столбцы, параметры и переменные XML могут хранить документы или контент XML, что указывается при помощи опции (DOCUMENT или CONTENT, соответственно, CONTENT по умолчанию) во время объявления. Более того, вам нужно обеспечить коллекцию схем XML. Указывайте DOCUMENT, если каждый экземпляр XML имеет один элемент верхнего уровня, иначе указывайте CONTENT. Компилятор запроса, видя установленный флажок DOCUMENT, подразумевает, что у экземпляра XML есть только один элемент верхнего уровня.

    Пример: типизированный столбец XML в таблице

    Столбцы, переменные и параметры XML могут быть сопоставлены коллекции схем XML (см. главу "Обработка схем XML" далее в этой статье для более подробного объяснения и большего количества примеров). Предположим, что myCollection является такой коллекцией. Команда, показанная ниже, создает таблицу XmlCatalog со столбцом типизированного XML Document, используя myCollection. Для столбца типизированного XML также указано, что он может хранить и фрагменты XML, а не только документы XML.

    
    CREATE TABLE XmlCatalog ( 
      ID INT PRIMARY KEY, 
      Document XML(CONTENT myCollection))
    


    Ограничения столбцов типа XML

    Кроме типизации столбца XML, Вы также можете использовать реляционные (для столбца или строки) ограничения на столбцах типизированного и нетипизированного XML. Вообще большинство ограничений SQL применимы к столбцам XML, исключениями являются ограничения уникального, первичного и внешнего ключей, т.к. экземпляры данных XML нельзя сравнивать. Таким образом, Вы можете указать, что столбец XML может или не может содержать значение NULL, определить у него значение по умолчанию и ограничение CHECK. Например, нетипизированный столбец XML может иметь ограничение CHECK для проверки, что хранимые экземпляры XML соответствуют схеме XML.

    Используйте ограничения, исходя из следующих условий:

    • Ваши бизнес-правила не могут быть представлены в схемах XML. Например, адрес доставки заказа из цветочного магазина должен находиться в пределах 50 миль от него, что может быть указано в виде ограничения столбца XML. Ограничение может включать методы для работы с типом XML.

    • Ваши ограничения включают другие XML или не XML столбцы в таблице. Например, ограничением является требование, чтобы ID покупателя (/Customer/@CustId) в экземпляре XML соответствовал значению столбца CustomerID типа integer.

    Пример: ограничение столбца XML

    Чтобы убедиться, что фамилия автора книги отличается от его имени, можно применить следующее ограничение CHECK:

    
    CREATE TABLE docs (pk INT PRIMARY KEY, 
      xCol XML not null
      CONSTRAINT CK_name CHECK 
        (xCol.exist('/book/author[first-name = last-name]') = 0))
    


    Кодировка текста

    SQL Server 2005 хранит данные XML в виде Unicode (UTF-16). Данные XML, полученные с сервера, приходят в кодировке UTF-16. Если Вы хотите другую кодировку, Вам нужно будет выполнить необходимую конвертацию после получения данных. Например, Вы можете преобразовать Ваши данные XML в тип varchar на сервере, в этом случае движок базы данных выдаст данные XML с кодировкой, определенной типом varchar.


    Хранение данных XML

    Вы можете передать значение XML для столбца, параметра или переменной XML несколькими способами.

    • Как символьный или двоичный тип SQL, который неявно конвертируется в тип XML.

    • Как содержимое файла.

    • Как результат механизма публикации XML - использование FOR XML с опцией TYPE, которая генерирует экземпляр данных XML.

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

    Для типизированного XML переданное значение проверяется на соответствие схемам XML, зарегистрированным в коллекции схем XML, сопоставленной столбцу XML. Экземпляр XML не вставляется в столбец, если он не проходит такую проверку. Более того, флажок DOCUMENT в типизированном XML ограничивает допустимые значения только документами XML, тогда как флажок CONTENT позволяет передавать и документ XML, и контент.

    Пример: вставка данных в нетипизированный столбец XML

    Следующая команда вставляет новую строку в таблицу docs со значением 1 для столбца pk и экземпляром <book> для столбца XML. Данные <book>, передаваемые в виде строки, неявно конвертируются в тип данных XML и проверяются на структурированность во время вставки.

    
    INSERT INTO docs VALUES (1, 
      '<book genre="security" publicationdate="2002" ISBN="0-7356-1588-2">
         <title>Writing Secure Code</title>
         <author>
           <first-name>Michael</first-name>
           <last-name>Howard</last-name>
         </author>
         <author>
           <first-name>David</first-name>
           <last-name>LeBlanc</last-name>
         </author>
         <price>39.99</price>
      </book>')
    

    Пример: вставка данных в нетипизированный столбец XML из файла

    Команда INSERT, показанная ниже, получает содержимое файла C:\temp\xmlfile.xml в виде BLOB, используя OPENROWSET. Новая строка вставляется в таблицу docs со значением 10 для первичного ключа и BLOB для столбца XML xCol. Проверка структурированности данных производится, когда содержимое файла назначается столбцу XML.

    
    INSERT INTO docs 
      SELECT 10, xCol
      FROM (SELECT * FROM OPENROWSET 
        (BULK 'C:\temp\xmlfile.xml',
          SINGLE_BLOB) AS xCol) AS R(xCol)
    

    Пример: вставка данных в типизированный столбец XML

    Типизированный столбец XML требует, чтобы данные экземпляра XML соответствовали пространству имен схем XML, используемых для типизации этого столбца (пространство имен может быть пустым). В показанном ниже примере это делается с помощью объявления пространства имен xmlns=http://myDVD.

    
    INSERT XmlCatalog VALUES(2, 
      '<?xml version="1.0"?>
      <dvdstore xmlns="http://myDVD">
        <dvd genre="Comedy" releasedate="2003">
          <title>My Big Fat Greek Wedding</title>
          <price>19.99</price>
        </dvd>
      </dvdstore>')
    

    Пример: сохранение данных XML, сгенерированных с помощью FOR XML с опцией TYPE

    FOR XML была расширена опцией TYPE, чтобы генерировать результат в виде экземпляра типа данных XML. Результирующий XML может быть занесен в столбец, параметр или переменную XML. В следующей команде экземпляр XML, сгенерированный с помощью FOR XML TYPE, присваивается переменной @xVar типа XML. Значение переменной можно получить с помощью методов типа XML.

    
    DECLARE @xVar XML
    SET @xVar = (SELECT * FROM docs FOR XML AUTO,TYPE)
    


    Представление данных при хранении

    Экземпляры XML хранятся во внутреннем, двоичном представлении, которое оптимизировано для эффективного парсинга. Тэги конвертируются в значения типа integer, и конвертированные значения хранятся во внутреннем представлении. Это дает небольшую компрессию данных.

    Для нетипизированного XML значения узлов хранятся в строках Unicode (UTF-16), поэтому требуется конверсия типа во время работы. Например, чтобы оценить предикат /book/price > 9.99, значение цены книги конвертируется в тип decimal. С другой стороны, для типизированного XML значения имеют тип, определенный схемами XML. Это делает парсинг данных более эффективным и позволяет избежать конвертации типов во время работы.

    Двоичная форма хранения ограничена 2 гигабайтами на экземпляр XML, что достаточно для большинства данных XML. Также глубина иерархии XML ограничена 128 уровнями.

    Содержимое InfoSet данных XML защищено. Оно может не быть точной копией текста XML, т.к. следующая информация не сохраняется: не имеющие значения пустые места, порядок свойств, префиксы пространства имен, и объявление XML.


    Взгляд на моделирование данных

    Довольно часто набор реляционных столбцов и столбцов XML удобен для моделирования данных. Некоторые значения из ваших данных XML могут храниться в реляционных столбцах, а остальные, или все значения XML, хранятся в столбце XML. Это может дать лучшую производительность и лучшие характеристики блокировок.

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

    Глубина детализации данных XML, хранящихся в столбцах XML, критична для блокировок и обновления. SQL Server использует один и то же механизм блокировки для XML и не XML данных. Если глубина детализации велика, то блокировка больших экземпляров XML для обновления вызывает снижение производительности при одновременной работе множества пользователей. С другой стороны, из-за глубокой декомпозиции данных теряется инкапсуляция объектов и увеличиваются затраты на сборку.


    Выполнение запросов и модификация данных XML

    Выполнение запросов к экземплярам XML, хранимым в столбце XML, требует парсинга двоичных данных XML в столбце. Парсинг двоичных данных XML производится гораздо быстрее, чем парсинг текстовой формы данных XML. Индексирование XML позволяет избежать повторного парсинга. Более подробно индексирование рассматривается в главе "Индексирование данных XML".


    Методы типа XML

    Вы можете получать целые значения XML, если Вам это нужно, или можете получать части экземпляров XML. Это возможно с помощью четырех методов типа XML: query(), value(), exist() и nodes(), которые принимают в в виде аргумента выражение XQuery. Пятый метод, modify(), позволяет изменять данные XML и принимает в виде входного параметра команду изменения данных XML.

    Метод query() полезен для получения частей экземпляра XML. Выражение XQuery сравнивается со списком узлов XML. Поддерево, получаемое на каждом из этих узлов, возвращается в порядке документа. Тип результата - нетипизированный XML.

    Метод value() получает скалярное значение из экземпляра XML. Он возвращает значение узла, который соответствует выражению XQuery. Это значение конвертируется в тип T-SQL, определяемый вторым параметром метода value().

    Метод exist() полезен для проверок существования в экземплярах XML. Он возвращает 1, если выражение XQuery соответствует непустому списку узлов, иначе он возвращает 0.

    Метод nodes() выдает экземпляры специального типа XML, каждый из которых имеет собственный контекст, относящийся к узлу, который соотвутствует выражению XQuery. Этот специальный тип XML поддерживает методы query(), value(), nodes() и exist(), и может быть использован в агрегатах count(*) и проверках на значение NULL. Все другие агрегаты и проверки вернут ошибку.

    Метод modify() позволяет изменять части экземпляра XML - добавлять или удалять поддеревья или изменять скалярные значения. Например, изменять цену на книгу с 9.99 на 39.99.

    Пример: использование метода query()

    Рассмотрим следующий запрос в столбце XML xCol таблицы docs, который получает все элементы <section> под элементом <doc> с id 123. Запрос также возвращает значение из столбца первичного ключа с типом integer. Метод query() в списке SELECT применяется для каждой строки в таблице, выдавая последовательность элементов <section>, которые возвращаются вместе со своими поддеревьями в порядке документов. Экземпляр XML без элемента <doc> с id 123 или без элемента <section> под ним результата не возвращает, т.е. метод query() возвращает NULL.

    
    SELECT pk, xCol.query('/doc[@id = 123]//section')   
    FROM docs
    

    Возвращаемые значения NULL могут быть отфильтрованы во внешней команде SELECT. Также можно использовать метод exist(), как показано в следующем примере.

    Пример: использование метода exist()

    Рассмотрим следующий запрос, который использует методы query() и exist() в столбце XML xCol таблицы docs. Метод exist() использует выражение пути /doc[@id = 123], проверяя существование элемента верхнего уровня <doc> со свойством id, равным 123. Для каждой такой строки применяется метод query() из команды SELECT; в этом примере метод query() возращает последовательность всех элементов <section> под элементом <doc>. Любая строка, в которой метод exist() возвращает 0, опускается.

    
    SELECT xCol.query('/doc[@id = 123]//section')   
    FROM docs
    WHERE xCol.exist ('/doc[@id = 123]') = 1
    

    Пример: использование метода value()

    Следующий запрос получает заголовок третьей секции документа в виде строки Unicode, используя метод value(). Тип SQL nvarchar(max) результата определяется как второй параметр метода value(). Функция XQuery data() выделяет скалярное значение из узла <heading>.

    
    SELECT xCol.value(
      'data((/doc//section[@num = 3]/heading)[1])', 
      'nvarchar(max)') 
    FROM docs
    


    Язык XQuery

    Существует множество источников XML из документов Office, находящихся в файловой системе, web сервисов и файлов конфигурации. Фактически, данные все чаще создаются либо в формате XML, либо в виде виртуального документа XML. Чтобы справиться с этим растущим объемом данных, был придуман мощный язык запросов XQuery. XQuery описан в спецификации XQuery Language на сайте http://www.w3.org/TR/xquery как язык запросов, который эффективно использует структуру XML и может выражать запросы по всем типам данных, которые физически хранятся в виде XML или просматриваются как XML через средний уровень. Спецификация описывает язык запросов XQuery, который разработан для широкого применения для многих типов источников данных XML.

    XQuery разработан для удовлетворения требованиям XML Query 1.0 рабочей группы W3C XML Query и примерам XML Query Use Cases. Он разработан как язык, в котором запросы понятны и кратки. Он также достаточно гибок для выполнения запросов широкого спектра источников данных XML, включая базы данных и документы. XQuery можно обобщить следующим утверждением: язык XQuery относится к XML так же, как язык SQL к реляционным базам данных.

    Подмножество XQuery, встроенное в T-SQL - это язык для выполнения запросов на типе XML. В настоящее время язык еще разрабатывается Worldwide Web Consortium (W3C) с участием всех главных поставщиков баз данных, включая Microsoft. Наша версия соответствует релизу от ноября 2003 года.

    XQuery включает XPath 2.0 как язык навигации. Реализация XQuery в SQL Server 2005 имеет конструкции для движения по узлам (for), проверки узлов (where), возврата значений (return) и сортировки (order by). Также есть возможность изменения данных во время выполнения запросов.

    SQL Server 2005 также имеет языковые конструкции для изменения данных (DML) типа XML (для дополнительной информации см. главу "Изменение данных" ниже). Следующий пример показывает, как использовать XQuery для данных типа XML.

    Пример: использование богатых языковых конструкций в XQuery

    Следующий запрос показывает несколько языковых конструкций XQuery, используемых вместе. Он возвращает заголовок, обрамленный в новый тэг <topic> с секциями номер 3 и далее из документа с id 123.

    
    SELECT pk, xCol.query('
      for $s in /doc[@id = 123]//section
      where $s/@num >= 3
      return <topic>{data($s/heading)}</topic>')   
    FROM docs
    

    Оператор "for" указывает на то, что нужно двигаться по всем элементам <section> под элементами <doc> с id 123 и привязывать каждый такой элемент <section> к переменной $s. Оператор "where" используется для того, чтобы номер секции (атрибут @num элемента <section>) равен или больше 3. Запрос возвращает значение секции <heading> по порядку документа, обрамленное элементом конструкции <topic>.


    Компиляция и выполнение запроса

    Команда SQL обрабатывается анализатором SQL. Когда он обнаруживает выражение XQuery, управление передается компилятору XQuery, который затем компилирует выражение XQuery. Это порождает дерево запросов.

    Общее дерево запросов выполняет оптимизацию запросов и строит физический план запросов, основанный на оценке затрат. Просмотр плана показывает большинство реляционных операторов и несколько новых операторов, таких, как UDX для обработки XML.

    Выполнение запросов ориентировано на строки, как и в реляционной модели. Выражение WHERE применяется к каждой строке таблицы docs; это включает анализ XML данных во время выполнения, чтобы применять методы типа XML. Если условие выполняется, то строка блокируется и выражение SELECT применяется к строке. Результат выводится в виде данных XML для метода query() и конвертируется в соответствующий тип для метода value().

    Если, напротив, строка не удовлетворяет условию выражения WHERE, то она пропускается и выполнение переходит на следующую строку.


    Изменение данных XML

    SQL Server 2005 имеет конструкции для изменения данных в виде расширения XQuery. Поддеревья могут вставляться перед или после определенного узла, или как самые левые или самые правые потомки. Более того, поддерево может быть вставлено в родительский узел, в этом случае оно становится самым правым потомком родителя. Поддерживаются вставки атрибутов, элементов и текстовых узлов.

    Также поддерживается удаление поддеревьев. В этом случае целые поддеревья удаляются из экземпляра XML.

    Скалярные значения могут заменяться новыми скалярными значениями.

    Пример: вставка поддеревьев в экземпляры XML

    Этот пример показывает использование метода modify() для вставки нового элемента <section> справа от элемента <section>, чей номер равен 1.

    
    UPDATE docs SET xCol.modify('
      insert 
        <section num="2">
          <heading>Background</heading>
        </section>                
      after (/doc/section[@num=1])[1]')
    

    Пример: обновление цены книги на значение $49.99

    Следующая команда обновления заменяет цену книги <price> с ISBN 1-8610-0311-0 на новое значение $49.99. Экземпляр XML типизирован схемой XML http://myBooks, поэтому в команде изменения данных XML объявляется пространство имен.

    
    UPDATE XmlCatalog
    SET Document.modify ('
      default namespace = "http://myBooks" 
      replace value of (/bookstore/book[@ISBN=
        "1-8610-0311-0"]/price)[1] with 49.99')
    


    Проверка типа и статические ошибки

    XQuery выполняет проверку типа. В фазе компиляции проверяется правильность статического типа выражений XQuery и команд изменения данных и используются схемы XML для ссылок на тип в случае типизированного XML. В случае нарушения типа во время выполнения генерируются ошибки статического типа. Примерами статических ошибок являются: добавление строки к числу, получение последовательности значений, если ожидается единственное значение, запрос к несуществующему узлу для типизированных данных. Явное преобразование типа используется, чтобы избежать статических ошибок несовпадения типа. Ошибки времени выполнения XQuery конвертируются в пустые последовательности.

    Параметры функций и операторы (например, eq), требующие единственного значения, возвращают ошибку, если компилятор не может определить, гарантировано ли единственное значение во время выполнения. Часто появляется проблема с нетипизированными данными. Например, поиск атрибута требует единственного родительского элемента.

    Пример: проверки типа в методе value()

    Следующий запрос по столбцу с нетипизированным XML требует спецификации //author/last-name, т.к. метод value() ожидает единственный узел в качестве первого аргумента. Без него компилятор не сможет определить, один ли узел <last-name> будет найден во время выполнения:

    
    SELECT xCol.value('(//author/last-name)[1]', 'nvarchar(50)') LastName
    FROM docs
    

    Применение комбинации node()-value() для получения значений атрибутов может не требовать спецификации, как показано в следующем примере:

    Пример: известное единственное значение

    Показанный ниже метод nodes() генерирует отдельную строку для каждого элемента <book>. Метод value(), применяемый на узле <book>, получает значение @genre, которое, будучи атрибутом, является единственным.

    
    SELECT nref.value('@genre', 'varchar(max)') LastName
    FROM docs CROSS APPLY xCol.nodes('//book') AS R(nref)
    


    Междоменные запросы

    Когда Ваши данные располагаются в комбинации реляционных столбцов и столбцов XML, Вы можете захотеть написать запросы, которые сочетают обработку реляционных и XML данных. Вы можете конвертировать данные в реляционных столбцах и столбцах XML в экземпляр XML, используя FOR XML с директивой TYPE и выполнить запрос, используя XQuery. И наоборот, Вы можете генерировать набор строк из значений XML и выполнить запрос, используя T-SQL, как показано в главе "Генерация набора строк из данных XML" ниже.

    Более удобным и эффективным путем написания междоменных запросов является использование значения переменной SQL или столбца внутри выражения XQuery или внутри выражения изменения данных XML:

    • Вставьте значение переменной SQL в Ваше выражение XQuery или выражение XML DML, используя sql:variable().

    • Используйте значения из реляционного столбца в XQuery или контексте XML DML с помощью sql:column().

    Этот подход позволяет приложениям параметризовать запросы, как показано в следующем примере. Sql:column() используется таким же образом и обеспечивает дополнительные преимущества. Для повышения эффективности могут быть задействованы индексы столбца, если это будет выбрано оптимизатором запросов. Кроме того, можно использовать вычислимые столбцы.

    Тип XML и пользовательские типы не разрешены для использования с sql:variable() и sql:column().

    Пример: междоменный запрос с использованием sql:variable()

    В этом запросе передается ISBN элемента <book> при помощи переменной SQL @isbn. Вместо константы, переменная sql:variable() содержит значение ISBN, и запрос может использоваться для поиска любого ISBN, а не только того, чье значение равно 0-7356-1588-2.

    
    DECLARE @isbn varchar(20)
    SET @isbn = '0-7356-1588-2'
    SELECT xCol
    FROM docs
    WHERE xCol.exist ('/book[@ISBN = sql:variable("@isbn")]') = 1
    


    Генерация набора строк из данных XML

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

    Для этой цели в SQL Server 2000 есть OpenXml(). Это средство для создания набора строк из экземпляра XML через определение реляционной схемы для набора строк и способа конвертации значений экземпляра XML в столбцы набора строк.

    И наоборот, метод nodes() может быть использован для генерации контекста узла внутри экземпляра XML; и контекст узла может использоваться в методах value(), query(), exist() и nodes() для создания желаемого набора строк. Метод nodes() получает выражение XQuery, применяет его к каждому экземпляру XML в столбце XML, и эффективно использует индексы XML. Следующий пример показывает использование метода nodes() для создания набора строк.

    Пример: получение свойств из экземпляра XML

    Предположим, Вам нужно получить имена и фамилии авторов, чье имя не "David", в наборе строк с двумя столбцами, FirstName и LastName. Вы можете сделать это, используя методы nodes() и value():

    
    SELECT nref.value('first-name[1]', 'nvarchar(50)') FirstName,
      nref.value('last-name[1]', 'nvarchar(50)') LastName
    FROM docs CROSS APPLY xCol.nodes('//author') AS R(nref)
    WHERE nref.exist('.[first-name != "David"]') = 1
    

    В этом примере nodes('//author') порождает набор ссылок на элементы <author> для каждого экземпляра XML. Имена и фамилии авторов получаются с помощью методов value(), относящихся к этим ссылкам. Для хорошей производительности столбец XML должен быть проиндексирован, что и является темой следующей главы.


    Индексирование данных XML

    Данные XML хранятся во внутренней двоичной форме, и могут достигать объема в 2 гигабайта. Каждый запрос анализирует данные XML в каждой строке таблицы один или несколько раз во время работы. Это приводит к замедлению обработки запроса. Если запрос часто повторяется, то лучше проиндексировать столбец XML, хотя и нужно принять во внимание возрастающие при этом затраты на изменение данных.

    Индексы XML создаются при помощи новой команды DDL на типизированных и нетипизированных столбцах XML. Индекс создает сбалансированное дерево по всем экземплярам XML в столбце. Первым создаваемым индексом на столбце XML является "первичный ключ XML". С его помощью поддерживаются три типа вторичных индексов XML на столбце XML для ускорения часто используемых классов запросов, как показано в следующей главе.


    Первичный индекс XML

    Первичный индекс XML требует наличия кластерного индекса на первичном ключе базовой таблицы (т.е. таблицы, в которой создан столбец XML). Первичный индекс XML создает сбалансированное дерево на поднаборе элементов Infoset узлов XML. Столбцы сбалансированного дерева представляют тэги, такие, как названия элементов и атрибутов, значения и типы узлов. Другие столбцы указывают порядок и структуру документов в данных XML и путь из корня экземпляра XML до каждого узла для эффективной оценки выражений пути. Первичный ключ базовой таблицы дублирован в первичном индексе XML для соответствия строк индекса со строками базовой таблицы.

    Тэги и названия типов из схем XML конвертируются в значения типа integer, и конвертированные значения хранятся в сбалансированном дереве для оптимизации хранения. Столбец пути в индексе хранит последовательность конвертированных значений в обратном порядке, т.е. от узла до корня экземпляра XML. Обратное представление позволяет сравнивать значения пути, если известен суффикс пути (в выражении пути, таком, как //author/last-name).

    Если основная таблица секционирована, то первичный индекс XML секционируется таким же образом, т.е. с использованием той же функции и схемы секционирования.

    Полные экземпляры XML получаются из столбцов XML (SELECT * FROM docs или SELECT xCol FROM docs). Запросы, включающие методы XML, используют первичный индекс XML и возвращают скалярные значения или поддеревья XML из самого индекса.

    Пример: создание первичного индекса XML

    Следующая команда создает индекс XML idx_xCol на столбце XML xCol таблицы docs:

    
    CREATE PRIMARY XML INDEX idx_xCol on docs (xCol)
    


    Вторичные индексы XML

    Когда создан первичный индекс XML, можно создать вторичные индексы XML, чтобы ускорить выполнение запросов разных классов. Три типа вторичных индексов XML - PATH, PROPERTY и VALUE - дают выигрыш в запросах, основанных на пути, сценариях управления пользовательскими свойствами, и запросах, основанных на значениях, соответственно.

    Индекс PATH строит сбалансированное дерево на столбцах (path, value) первичного индекса XML. Значение для пути рассчитывается из выражения пути; значение узла также используется, если оно существует. С известными основными полями индекса PATH поиск по индексу PATH увеличивает обработки выражения пути. Наиболее распространенным случаем является использование метода exist() на столбцах XML в выражении WHERE команды SELECT.

    Индекс PROPERTY создает сбалансированное дерево на столбцах (PK, path, value) первичного индекса XML, где PK - первичный ключ базовой таблицы. Этот индекс помогает искать значения свойств в экземпляре XML.

    И, наконец, индекс VALUE создает сбалансированное дерево на столбцах (value, path) первичного индекса XML. Этот индекс ускоряет выполнение запросов, где значение узла известно, но его путь неточно определен в запросе. Такая ситуация обычно возникает при поиске типа descendant-or-self, как, например, в //author[last-name="Howard"], где элементы <author> могут встретиться на любом уровне иерархии. Такая ситуация также возникает в запросах со специальными символами, таких, как /book [@* = "novel"], где запрос ищет элементы <book> с атрибутом, имеющим значение "novel". Индекс VALUE также полезен для сканирования набора значений для типизированного XML.

    В иерархии XML может размещаться до 128 уровней; экземпляры XML, содержащие более длинные пути, не принимаются при вставке и изменении.

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

    Пример: поиск, основанный на пути

    Предположим, что следующий запрос часто выполняется:

    
    SELECT xCol
    FROM   docs
    WHERE  xCol.exist ('/book[@genre = "novel"]') = 1
    

    Выражение пути /book/@genre и значение "novel" соответствуют ключевым полям индекса PATH. Соответственно, вторичный индекс XML типа PATH может помочь в этом случае:

    
    CREATE XML INDEX idx_xCol_Path on docs (xCol)
      USING XML INDEX idx_xCol FOR PATH
    

    Пример: получение свойств объекта

    Рассмотрим следующий запрос, который получает свойства "genre", "title" и ISBN книги из каждой строки в таблице T:

    
    SELECT xCol.value ('(/book/@genre)[1]', 'varchar(50)'),
      xCol.value ('(/book/title)[1]', 'varchar(50)'),
      xCol.value ('(/book/@ISBN)[1]', 'varchar(50)')
    FROM docs
    

    В этом случае можно использовать индекс свойств:

    
    CREATE XML INDEX idx_xCol_Property on docs (xCol)
      USING XML INDEX idx_xCol FOR PROPERTY
    

    Пример: запрос, основанный на значениях

    В следующем запросе ось потомков descendant-or-self (//) определяет частичный путь, поэтому индекс VALUE помогает выполнять поиск, основанный на значениях ISBN:

    
    SELECT xCol
    FROM   docs
    WHERE  xCol.exist ('//book[@ISBN = "1-8610-0157-6"]') = 1
    

    Индекс VALUE создается следующим образом:

    
    CREATE XML INDEX idx_xCol_Value on docs (xCol)
      USING XML INDEX idx_xCol FOR VALUE
    


    Индексирование содержимого

    Вы можете создать полнотекстовый индекс на столбцах XML; это индексирует содержимое значений XML, игнорируя разметку XML. Значения атрибутов не входят в полнотекстовый индекс (так как они считаются частью разметки), и тэги элемента используются как разграничительные знаки. Вы можете создавать и индексы XML, и полнотекстовые индексы на столбце XML, и совмещать полнотекстовый поиск с использованием индекса XML. Используйте полнотекстовый индекс в качестве первого фильтра, чтобы уменьшить выборку и потом применить XQuery для дальнейшей фильтрации.

    Полнотекстовый поиск, использующий CONTAINS(), и contains() языка XQuery имеют разную семантику. Последний метод выполняет сравнение подстроки, а первый выполняет сравнение при помощи разграничительных знаков.

    Пример: создание полнотекстового индекса на столбце XML

    Шаги, требующиеся для создания полнотекстового индекса на столбце XML, не сильно отличаются от тех, которые выполняются для столбцов других типов. В основной базе необходим уникальный ключ на столбце. Ниже показаны команды DDL, в которых PK__docs__7F60ED59 - первичный ключ на одном столбце таблицы:

    
    CREATE FULLTEXT CATALOG ft AS DEFAULT
    CREATE FULLTEXT INDEX ON dbo.docs (xCol) KEY INDEX PK__docs__7F60ED59
    

    Пример: совмещение полнотекстового поиска с запросами XML

    Следующий запрос проверяет, что значение XML содержит слово "Secure" в названии книги:

    
    SELECT * 
    FROM   docs 
    WHERE  CONTAINS(xCol,'Secure') 
    AND    xCol.exist('/book/title/text()[contains(.,"Secure")]') =1
    

    Метод CONTAINS() использует полнотекстовый индекс для выборки из документа значений XML, которые содержат слово "Secure". Метод exist() проверяет, что слово "Secure" содержится в названии книги.


    Выполнение запроса с использованием индексов XML

    Индексы XML ускоряют выполнение запросов. Запросы всегда компилируются по первичному индексу столбца XML, если он существует. Один план выполнения создается для всего запроса (и для реляционной части, и для части XML), который оптимизируется при помощи оптимизатора запросов движка базы данных. Вторичные индексы XML выбираются для использования в соответствии с оценками затрат оптимизатора запросов.


    Каталожные представления для индексов XML

    Каталожные представления используются для просмотра индексов XML с типом индекса 3 (столбец "type"). В столбце "name" содержится название индекса XML.

    Индексы XML также находятся в каталожном представлении sys.xml_indexes, в котором содержатся все столбцы из sys.indexes и несколько дополнительных, имеющих отношение к индексам XML. Значение NULL в столбце "secondary_type" указывает на первичный индекс XML; значения 'P', 'R' and 'V' соответствуют вторичным индексам XML PATH, PROPERTY и VALUE.

    Использование пространства в индексах XML может быть проверено при помощи табличной функции sys.fn_indexinfo(). Функция возвращает такую информацию, как количество занятых страниц на диске, средний размер строки в байтах, количество записей, и другую информацию для индексов всех типов, включая индексы XML. Эта информация доступна для каждой секции базы данных; индексы XML используют ту же схему секционирования и функцию секционирования базовой таблицы.

    Пример: использование пространства в индексах XML

    
    SELECT sum(Pages)
    FROM   sys.fn_indexinfo ('docs', 'idx_xCol_Path' , DEFAULT, 'DETAILED')
    

    Эта команда SELECT выводит количество страниц на диске, занятых индексом XML idx_xCol_Path в таблице T по всем секциям. Без функции sum() результат возвратил бы количество занятых страниц на диске по каждой секции.


    Обработка схем XML

    Использование схем XML необязательно. Как уже упоминалось ранее, данные типа XML, не привязанные к схемам XML, являются нетипизированными; значения узла XML хранятся в виде строк Unicode, и экземпляры XML проверяются на корректность. Нетипизированный столбец XML может быть индексированным.

    Превращение данных XML в типизированные данные производится с помощью привязки данных XML к схемам XML, зарегистрированным в коллекции схем XML. Новая команда DDL позволяет создать коллекцию схем XML, в которой можно зарегистрировать одну или несколько схем XML. Столбец, параметр или переменная XML, привязанные к коллекции схем XML, являются типизированными в соответствии со всеми схемами XML в коллекции. Внутри коллекции схем XML система типов определяет каждую схему XML, используя ее пространство имен.

    Каждый элемент XML верхнего уровня в экземпляре XML должен определять пространство имен (возможно, пустое), которое ему соответствует. Данные проверяются на соответствие пространству имен каждого элемента во время вставки и изменения. Двоичное представление XML кодирует типизированные значения на основе информации соответствующей схемы XML, поэтому анализ XML в данном случае является более эффективным по сравнению с нетипизированным XML, т.к..значения в индексах XML имеют правильный тип (/book/price хранится как decimal, если определено в схеме XML как xs:decimal).

    Во время компиляции запроса схемы XML используются для проверки типа, и в случае несоответствия типов генерируются ошибки. Компилятор запросов также использует схемы XML для оптимизации запросов.

    Подсистема метаданных ядра базы данных содержит информацию о типе XML, такую, как коллекции схем XML и содержащиеся в них схемы, а также конвертацию между XSD и реляционными системой. Поддерживается почти вся спецификация W3C XML Schema 1.0 (для дополнительной информации смотрите http://www.w3.org/TR/2001/REC-xmlschema-1-20010502/ и http://www.w3.org/TR/2001/REC-xmlschema-2-20010502/). Комментарии и аннотации в документах схем XML не защищены и key/keyref не поддерживается.


    Коллекция схем XML

    Коллекция схем XML - это объект метаданных, ограниченная реляционной схемой и содержащая одну или более схем XML, которые могут быть связанными (например, используя <xs:import>) или несвязанными. Индивидуальные схемы внутри коллекции схем XML определяются с помощью их пространства имен. Коллекции схем XML - это защищенные как таблицы объекты.

    Коллекция схем XML создается с помощью CREATE XML SCHEMA COLLECTION и содержит одну или более схем XML. После этого Вы можете типизировать столбец XML, используя коллекцию схем XML. Такой дизайн приводит к гибкой модели данных, в которой значения XML, типизированные в соответствии с разными схемами XML, могут храниться в одном и том же столбце. Это особенно удобно, когда количество схем XML большое. Более того, такой дизайн до некоторой степени поддерживает развитие схемы XML.

    Кроме того, опция DOCUMENT / CONTENT в типизированном столбце XML определяет, что в столбце XML могут храниться деревья XML или фрагменты XML, соответственно. Значение по умолчанию - CONTENT. Для значения DOCUMENT каждый экземпляр XML должен определять пространство имен его элемента верхнего уровня, в соответствии с которым он проверяется и типизируется. С другой стороны, для CONTENT каждый элемент верхнего уровня может определять любое из пространств имен в коллекции схем XML. Экземпляр XML проверяется и типизируется в соответствии со всеми пространствами имен, имеющимися в экземпляре.

    Пример: создание коллекции схем XML

    Предположим, что Вы хотите использовать схему XML с пространством имен http://myBooks, чтобы типизировать ваши экземпляры XML. Создайте коллекцию схем XML myCollection и добавьте в нее схему XML, как показано ниже:

    
    CREATE XML SCHEMA COLLECTION myCollection AS 
    '<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
      xmlns="http://myBooks"
       elementFormDefault="qualified"
      targetNamespace="http://myBooks">
      <xsd:element name="bookstore" type="bookstoreType" />
      <xsd:complexType name="bookstoreType">
       <xsd:sequence maxOccurs="unbounded">
         <xsd:element name="book" type="bookType" />
       </xsd:sequence>
      </xsd:complexType>
      <xsd:complexType name="bookType">
       <xsd:sequence>
         <xsd:element name="title" type="xsd:string" />
         <xsd:element name="author" type="authorName" />
         <xsd:element name="price" type="xsd:decimal" />
       </xsd:sequence>
       <xsd:attribute name="genre" type="xsd:string" />
       <xsd:attribute name="publicationdate" type="xsd:string" />
       <xsd:attribute name="ISBN" type="xsd:string" />
      </xsd:complexType>
      <xsd:complexType name="authorName">
       <xsd:sequence>
         <xsd:element name="first-name" type="xsd:string" />
         <xsd:element name="last-name" type="xsd:string" />
       </xsd:sequence>
      </xsd:complexType>
    </xsd:schema>'

    Новый объект метаданных создается для myCollection, в которой регистрируется схема XML.


    Изменение коллекции схем XML

    Команда ALTER XML SCHEMA COLLECTION поддерживает расширение схемы XML в коллекции схем XML новыми компонентами схемы верхнего уровня и регистрацию новых схем XML в коллекции схем XML. Это показано в следующем примере:

    Пример: изменение коллекции схем XML

    Следующая команда показывает, как новая схема XML с пространством имен http://myDVD может быть добавлена к коллекции схем XML myCollection:

    
    ALTER XML SCHEMA COLLECTION myCollection ADD
    '<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
      xmlns="http://myDVD"
       elementFormDefault="qualified"
      targetNamespace="http://myDVD">
      <xsd:element name="dvdstore" type="dvdstoreType" />
      <xsd:complexType name="dvdstoreType">
       <xsd:sequence maxOccurs="unbounded">
         <xsd:element name="dvd" type="dvdType" />
       </xsd:sequence>
      </xsd:complexType>
      <xsd:complexType name="dvdType">
       <xsd:sequence>
         <xsd:element name="title" type="xsd:string" />
         <xsd:element name="price" type="xsd:decimal" />
       </xsd:sequence>
       <xsd:attribute name="genre" type="xsd:string" />
       <xsd:attribute name="releasedate" type="xsd:string" />
      </xsd:complexType>
    </xsd:schema>'


    Каталожные представления для коллекций схем XML

    Каталожные представления SQL коллекций схем XML позволяют пользователям перестраивать содержимое индивидуальных пространств имен схем XML. Коллекции схем XML перечислены в каталожном представлении sys.xml_schema_collections. Коллекция схем XML "sys" определена системой и содержит предопределенные пространства имен, которые могут использоваться во всех пользовательских коллекциях схем XML без потребности явно загружать их. Эти пространства имен включают в себя пространства имен для xml, xs, xsi, fn и xdt.

    Два других каталожных представления, заслуживающих внимания: sys.xml_schema_namespaces, которое перечисляет все пространства имен внутри каждой коллекции схем XML; и sys.xml_components, которое перечисляет все компоненты схемы XML внутри каждой схемы XML.

    В встроенную функцию XML_SCHEMA_NAMESPACE() можно передать имя реляционной схемы, коллекции схем XML или пространство имен схемы XML. Функция возвращает экземпляр XML, содержащий схему XML. Если аргумент пространства имен не передан, встроенная функция возвращает экземпляр XML, который содержит все схемы XML в коллекции схем XML, кроме предопределенных схем XML.

    Пример: получение списка пространств имен XML в коллекции схем XML.

    Используйте следующий запрос для коллекции схем XML "myCollection":

    
    SELECT XSN.name
    FROM    sys.xml_schema_collections XSC 
     JOIN sys.xml_schema_namespaces XSN ON 
    (XSC.xml_collection_id = XSN.xml_collection_id)
    WHERE    XSC.name = 'myCollection'

    Пример: получение определенной схемы XML из коллекции схем XML.

    Следующая команда позволяет получить схему XML с пространством имен http://myBooks из коллекции схем XML "myCollection" внутри реляционной схемы dbo.

    
    SELECT XML_SCHEMA_NAMESPACE (N'dbo', N'myCollection', 
    N'http://myBooks')


    Контроль доступа к коллекциям схем XML

    Коллекции схем XML могут быть защищены, как любой объект SQL, используя модель безопасности SQL Server 2005. Вы можете дать пользователю права на создание коллекций схем XML внутри базы данных. Каждая коллекция схем XML поддерживает разрешения ALTER, CONTROL, TAKE OWNERSHIP, REFERENCES, EXECUTE и VIEW DEFINITION.

    Разрешение ALTER нужно для выполнения команды ALTER XML SCHEMA COLLECTION.

    Разрешение TAKE OWNERSHIP нужно для передачи владения коллекцией схем XML от одного пользователя к другому при помощи команды ALTER AUTHORIZATION.

    Разрешение REFERENCES дает пользователю возможность использовать коллекции схем XML, когда требуется привязка схемы, например, для типизирования или ограничения столбцов и параметров XML.

    Разрешение EXECUTE требуется для проверки при помощи коллекции схем XML значений, вставленных или обновленных пользователем. Это также нужно для выборки значений из типизированных столбца, переменной и параметра XML, используя тип данных XML.

    Разрешение VIEW DEFINITION дает пользователю доступ к строкам в каталожных представлениях, имеющих отношение к коллекциям схем XML, всем содержащимся в коллекциях схемам, и всем компонентам, содержащимся в схемах XML.

    Разрешение CONTROL позволяет пользователю выполнять любые операции над коллекцией схем XML, включая удаление коллекции схем XML, используя команду DROP XML SCHEMA COLLECTION. Это разрешение влияет на другие разрешения на коллекции схем XML.

    Права доступа на коллекцию схемы XML требуются в дополнение к другим правам доступа на таблице или столбце XML. Пользователю требуются права доступа для создания таблиц и разрешение REFERENCES на коллекции схем XML C, чтобы создать таблицу T со столбцом XML X, типизированным согласно C. Пользователь с разрешением на вставку данных в столбец X может делать это, если у него также есть разрешение EXECUTE на коллекции схем XML C. Аналогично, пользователю требуется разрешение SELECT на столбце X и разрешение EXECUTE на C для выборки данных из столбца X, используя методы XML. Однако, разрешение SELECT на X достаточно для получения полных значений XML из столбца X, таких, как SELECT X FROM T или SELECT * FROM T.

    Разрешения могут быть отозваны у пользователя, и пользователю могут быть запрещены права доступа, согласно модели безопасности SQL Server 2005.


    Видимость каталожных представлений

    Пользователь, имеющий разрешения ALTER, TAKE OWNERSHIP, REFERENCES, VIEW DEFINITION или CONTROL на коллекции схем XML, имеет доступ к строкам каталожных представлений, относящихся к коллекции схем XML, содержащимся в коллекции схемам XML, и их компонентам. Пользователь также имеет доступ к содержимому коллекции схем XML при помощи встроенной функции XML_SCHEMA_NAMESPACE().

    Если пользователю запрещено разрешение VIEW DEFINITION, то пользователь не имеет доступа к коллекции схем XML при помощи каталожных представлений или функции XML_SCHEMA_NAMESPACE().


    Улучшения в FOR XML

    Директива TYPE создает экземпляр XML, который может быть присвоен столбцу, переменной или параметру XML, или может быть выбран, используя методы XML.

    Режим PATH позволяет пользователю определять путь в дереве XML, где должны находиться значения столбцов, что более удобно, чем FOR XML EXPLICIT, хотя этот режим и не может работать с глубокими иерархиями.

    Директива XSINIL, используемая в связке с ELEMENTS, конвертирует NULL в элемент с атрибутом xsi:nil="true". Новая директива ROOT позволяет определять корневой узел во всех режимах FOR XML. Новая директива XMLSCHEMA создает внутреннюю схему XSD.

    Для дополнительной информации об улучшениях в FOR XML, смотрите статью " What's New in FOR XML in Microsoft SQL Server" Michael Rys, опубликованную в MSDN в июне 2004.


    Руководство по производительности

    Модель данных XML более сложна и богата, чем реляционная. Модель данных XML не только позволяет вам моделировать сложные данные, но она должна также защищать иерархические отношения и порядок документов внутри данных. Порядок документа поддерживается сортировкой, основанной на идентификаторах узлов XML; это также поддерживает иерархические отношения. Это приводит к более сложному плану выполнения.

    Для лучшей производительности структурированные данные должны храниться в реляционных столбцах таблиц. Выбирайте модель данных XML, если Ваши данные частично структурированы или неструктурированны, и содержат разметку XML, но не ожидайте улучшения производительности. Схемы XML помогают в оптимизации запросов.


    Поддержка XML в SQL Server CLR

    Используя поддержку SQL Server CLR, вы можете писать логику на серверной стороне в управляемом коде для поддержки бизнес-правил. Бизнес-логика может быть добавлена в данные XML следующими способами:

    Вы можете писать функции SQLCLR в управляемом коде, в который вы передаете значения XML, и использовать возможности обработки XML, предоставленные пространством имен System.Xml. Ниже показан пример трансформации XSL в данные XML. Вы также можете разложить XML на один или больше управляемых классов и оперировать ими, используя управляемый код. Вы можете написать хранимые процедуры и функции T-SQL, которые вызывают обработку столбца XML.

    Пример: применение трансформации XSL

    Рассмотрим функцию CLR TransformXml(), которая принимает в качестве аргумента экземпляр XML и трансформацию XSL, применяет трансформацию к данным XML, и возвращает измененный XML. Схематично функция, написанная на C#, выглядит следующим образом:

    
    public static SqlXml TransformXml (SqlXml XmlData, string xslPath) {
       // Load XSL transformation
       XslTransform xform = new XslTransform();
       XPathDocument xslDoc = new XPathDocument (xslPath);
       xform.Load (xslDoc.CreateNavigator(),null);
    
       // Load XML data
       XPathDocument xDoc = new XPathDocument (XmlData.CreateReader());
       XPathNavigator nav = xDoc.CreateNavigator ();
    
       // Return the transformed value
       SqlXml retSqlXml = new SqlXml (xform.Transform(nav, null));
       return (retSqlXml);
    }
    

    Когда сборка зарегистрирована и создана пользовательская функция T-SQL SqlXslTransform(), соответствующая функции CLR TransformXml(), то эта функция может быть вызвана из T-SQL следующим запросом:

    
    SELECT SqlXslTransform (xCol, 'C:\yukon\xsltransform.xsl')
    FROM    T
    WHERE  xCol.exist('/book/title/text()[contains(.,"custom")]') =1
    

    Результат запроса содержит набор записей трансформированного XML.

    SQLCLR открывает новые возможности по разложению данных XML в таблицы и запрашиванию данных XML, используя управляемые классы в пространстве имен System.Xml. Дополнительную информацию вы сможете найти в системах справки SQL Server 2005 и Visual Studio® 2005.


    Обработка XML на стороне клиента в SQL Server 2005

    Поддержка XML на стороне клиента

    Поддержка ADO.NET XML в .NET Framework V2.0

    Тип XML рассматривается как класс SqlXml в пространстве имен System.Data.SqlTypes метода SqlDataReader.GetSqlXml(). Вы можете получить XmlReader из объекта SqlXml, используя функцию SqlXml.CreateReader().

    Имя коллекции схем XML, состоящее из трех частей, которая типизирует столбец XML, можно получить из метаданных столбца XML (используя GetSchemaTable() или GetSqlMetaData (int) объекта SqlDataReader) в виде трех свойств, содержащих имя базы данных (XmlSchemaCollectionDatabase), реляционную схему (XmlSchemaCollectionOwingSchema) и коллекцию схем XML (XmlSchemaCollectionName).

    Новый набор данных схемы XMLSCHEMA доступен пользователям для получения схем XML с сервера. Набор данных XMLSCHEMA содержит три столбца для коллекции схем XML, пространства имен, и самого содержимого схемы XML.

    Следующие примеры показывают код для управляемого доступа к данным XML.

    Пример: встроенный доступ к данным XML

    Код на C#, показанный ниже, демонстрирует, как можно получить доступ к данным XML из встроенного провайдера. Код для доступа клиента SQL требует встроенного доступа.

    
    using System;
    using System.Xml;
    using System.Data;
    using System.Data.SqlTypes;
    using System.Data.SqlServer;
    
    class xmldtADONETReadAccessInProc
    {
       static void ReadXmlDataType () {
          // Встроенное соединение с сервером
          SqlConnection conn = SqlContext.GetConnection();
    
          // Подготовка запроса для выборки данных XML
          SqlCommand cmd = conn.CreateCommand();
          cmd.CommandText = "SELECT xCol FROM docs";
    
          // Выполнение запроса и получение данных
          SqlDataReader r = cmd.ExecuteReader();
          r.Read();
    
          // Доступ к столбцу с данными XML в наборе данных
          SqlXml xml = r.GetSqlXml(0);
          new XmlTextWriter(Console.Out).WriteNode( 
    xml.CreateReader(), true);
       }
    }
    

    Пример: обновление столбца XML с использованием клиентского провайдера SQL

    Код ниже демонстрирует метод WriteXmlDataType(), который изменяет значение столбца XML, используя клиентский провайдер SQL. Код для встроенного провайдера такой же.

    
    using System;
    using System.Xml;
    using System.Data;
    using System.Data.SqlTypes;
    using System.Data.SqlClient;
    
    class xmldtADONETUpdateAccess
    {
       static void WriteXmlDataType () {
          // Соединение с сервером
          SqlConnection conn = new SqlConnection("server=server1;" +
    " database=XMLtest; Integrated Security=SSPI");
          conn.Open();
    
       // Обновление столбца XML на сервере
       SqlCommand cmd = conn.CreateCommand();
       cmd.CommandText = "UPDATE docs SET xCol=@x WHERE id=1";
    
    // Установка значения параметра XML
       SqlParameter p = cmd.Parameters.Add("@x", SqlDbType.Xml);
    p.Value = new SqlXml(new XmlTextReader("<hello/>", 
    XmlNodeType.Document, null));
    
    // Выполнение обновления и закрытие соединения
       cmd.ExecuteNonQuery();
    conn.Close();
    }
    }
    


    Встроенный клиентский доступ к SQL

    В провайдере OLE DB нового встроенного доступа к SQL (SQLNCLI) столбец XML может быть получен как в виде строки Unicode (DBTYPE_XML, DBTYPE_BSTR, DBTYPE_WSTR и DBTYPE_VARIANT), так и в виде потока символов Unicode, используя ISequentialStream. По умолчанию используется DBTYPE_XML.

    Имя коллекции схем XML, состоящее из трех частей, передается тремя новыми столбцами в наборе данных схемы COLUMNS, возвращаемом IDBSchemaRowset::GetRowset(): столбцом SS_XML_CATALOGNAME, передающим название каталога; столбцом SS_XML_SCHEMANAME, передающим имя реляционной схемы, в которой размещается коллекция схем XML, и столбцом SS_XML_SCHEMACOLLECTIONNAME, передающим имя коллекции схем XML. Эти имена принадлежат типу DBTYPE_WSTR. Столбцы имеют значение NULL для нетипизированного столбца XML.

    Такие же изменения были сделаны в наборе данных схемы PROCEDURE_PARAMETERS и в IColumnRowset:GetColumnRowset().

    Чтобы получить содержимое коллекции схем XML, клиент может создать отдельный доступ к серверу, используя эти имена в вызове XML_SCHEMA_NAMESPACE(), и получить схемы XML в виде данных XML. Также IDBSchemaRowset с новым набором данных схемы SS_XMLSCHEMA возвращает имя каталога, имя реляционной схемы, имя коллекции схем XML, пространство имен и схему XML.

    Для доступа ODBC с помощью SQLNCLI, данные XML конвертируются в символьные данные Unicode, называемые SQL_SS_XML. Имя коллекции схем XML, состоящее из трех частей, передается через SqlColAttribute для столбца XML CharacterAttributePtr. Идентификаторы полей следующие: SQL_DESC_SS_XML_SCHEMA_CATALOG_NAME, SQL_DESC_SS_XML_SCHEMA_SCHEMA_NAME и SQL_DESC_SS_XML_SCHEMA_COLLECTION_NAME для имен базы данных, реляционной схемы и коллекции схем XML, соответственно.

    Пользователи должны устанавливать сервер базы данных или клиентские инструменты SQL Server 2005, чтобы получить встроенный клиентский доступ к SQL. Доступ OLE DB к данным XML, с использованием MDAC 2.8 ADO, невозможен.

    [В начало]

    Конвертация SQLXML между XML и реляционными схемами

    Вы можете создать логические представления XML Ваших реляционных данных, используя технологию конвертации SQLXML. Представление XML, также называемое "конвертацей" или "аннотируемой схемой", создается с помощью добавления специальных аннотаций к существующей схеме XSD. После этого другие технологии SQLXML могут использовать эту аннотируемую схему для трансформации запросов и обновлений логического представления XML в запросы и обновления реляционных таблиц:

    Когда представление XML комбинируется с запросом XPath, SQLXML сгенерирует запрос FOR XML, чтобы найти запрошенные данные и оформить их, как определено в схеме. Апдейтаграммы SQLXML отражают изменения в экземпляре XML, который, будучи совмещенным с аннотируемой схемой, вносит эти изменения в реляционную структуру с оптимистической блокировкой, чтобы удостовериться, что обновились нужные данные. SQLXML Bulkload использует представление XML, чтобы "разрезать" данные XML на реляционные таблицы. Для дополнительной информации обратитесь к документации по SQLXML.


    Создание представления XML реляционных таблиц

    Чтобы создать представление XML базы данных, начните со схемы XSD для ваших данных XML. Строки таблицы/представления базы данных будут конвертироваться в элементы сложного типа в схеме. Значения столбцов в базе данных конвертируются в атрибуты или элементы простого типа.

    По умолчанию, если не задано явных аннотаций, SQLXML предполагает, что элементы сложного типа будут конвертироваться в таблицы, а элементы простого типа и атрибуты - в столбцы. Это работает, только если имена элементов и атрибутов точно соответствуют именам таблиц и столбцов в Вашей базе данных.

    Если имя элемента/атрибута не такое, как имя таблицы/представления или имя столбца, с которым он конвертируется, то должна быть создана явная конвертация. Следующие аннотации используются для определения конвертации между элементом или атрибутом в документе XML и таблицей (представлением) или столбцом в базе данных:

    * sql:relation - конвертирует элемент XML в таблицу базы данных.
    * sql:field - конвертирует элемент или атрибут в столбец базы данных.


    Конвертация отношений для создания иерархий в представлениях XML

    В Вашей базе данных таблицы могут быть связаны внешними ключами. В XML эти же отношения отражаются в виде иерархии элементов. Чтобы создать правильную иерархию в Вашей конвертации, Вы должны определить, как элементы связаны между собой. Вы можете установить эти связи между элементами схемы конвертации, используя аннотацию sql:relationship. В этой аннотации Вы можете определить родительские и дочерние таблицы, как и столбцы в каждой из них, которые должны использоваться для выполнения объединения. Тогда SQLXML будет использовать эту информацию для создания правильной иерархии для вашей конвертации.


    Использование столбца overflow для хранения нераспределенных данных

    Конвертация работает, когда Ваши данные XML имеют постоянную структуру. Однако, могут быть некоторые данные в Вашем XML, которые или не структурированы, или не конвертируются в специальный столбец. Для хранения этих данных и дальнейшего их получения может использоваться аннотация sql:overflow. Аннотация sql:overflow определяет столбец, в котором хранится вся нераспределенная информация, и из которого ее можно получить запросами.

    Столбец overflow также подходит для расширения XML без необходимости добавления нового столбца в Вашу базу данных. Элементы и атрибуты могут быть добавлены к Ввашей структуре XML в любое время без добавления столбцов для их хранения в базе данных. Они просто будут храниться в поле overflow, и могут быть получены в нужное время.


    Дополнительная информация

    Для дополнительной информации по созданию представлений XML и примеров конвертации смотрите "Создание представлений XML с помощью аннотируемых схем XSD".


    Выполнение запросов к представлениям XML с использованием XPath

    Создав представление XML в базе данных, Вы можете выполнять запросы к этому представлению так же, как если бы действительно существовал документ XML, используя язык запросов XPath. SQLXML поддерживает подмножество языка запросов XPath 1.0. Когда XPath используется вместе с конвертацией, SQLXML создает команду FOR XML EXPLICIT, которая посылается в SQL Server. Результирующие данные получаются и форматируются в соответствии с конвертацией.

    Для дополнительной информации о подиножестве XPath, поддерживаемом представлениями XML, смотрите документацию о SQLXML.


    Обновление через представления XML с использованием апдейтаграмм

    Вы можете изменять (вставлять, обновлять или удалять) данные в базе данных SQL Server через представление XML, используя апдейтаграмму на представлении XML Вашей базы данных.


    Структура апдейтаграммы

    Апдейтаграмма - это документ XML с элементами <sync>, <before> и <after>, которые формируют синтаксис апдейтаграммы. Каждый блок <sync> содержит один или более блоков <before> и <after>. <before> отражает существующее состояние (также называемое "состояние до") экземпляра записи. <after> определяет новое состояние после изменения данных. Удаляет ли апдейтаграмма экземпляр записи, вставляет его или обновляет, зависит от содержимого блоков <before> и <after>.


    Операции вставки

    Апдейтаграмма указывает на операцию вставки, если экземпляр записи появляется в блоке <after>, но отсутствует в соответствующем блоке <before>. В этом случае апдейтаграмма вставляет запись из блока <after> в базу данных.


    Операции удаления

    Апдейтаграмма указывает на операцию удаления, если экземпляр записи появляется в блоке <before>, но отсутствует в соответствующем блоке <after>. В этом случае апдейтаграмма удаляет из базы данных запись из блока <before>.

    If an element that is specified in the updategram either matches more than one row in the table or does not match any table row, the updategram returns an error and cancels the entire <sync> block. Only one record at a time can be deleted by an element in the updategram.

    Если элемент, который определен в апдейтаграмме совпадает с более чем одной строкой в таблице или не совпадает ни с одной строкой, то апдейтаграмма возвращает ошибку и отменяет выполнение всего блока <sync>. За один раз при помощи элемента апдейтаграммы можно удалить только одну запись.


    Операции обновления

    Когда Вы обновляете существующие данные, Вы должны определить оба блока <before> и <after>. Апдейтаграмма использует элементы, которые определены в блоке <before>, чтобы идентифицировать существующие записи в базе данных. Соответствующие элементы в блоке <after> показывают, как должны выглядеть записи после выполнения операции обновления.

    Элемент в блоке <before> должен совпадать только с одной строкой таблицы в базе данных. Если элемент совпадает с множеством строк талблицы или не совпадает ни с одной строкой, то апдейтаграмма возвращает ошибку и отменяет выполнение всего блока <sync>.


    Дополнительная информация

    Для дополнительной информации о создании и использовании апдейтаграмм для изменения данных через представления XML смотрите Использование апдейтаграмм для изменения данных.


    Bulk загрузка данных XML через представления XML

    Bulk загрузка XML - это COM-объект, который позволяет Вам загружать данные XML в таблицы SQL Server. Вы можете вставлять данные XML в базу данных SQL Server, используя команду INSERT и функцию OPENXML; однако утилита bulk загрузки обеспечивает более высокую производительность, когда Вам нужно вставить большое количество данных XML. Bulk загрузка XML обрабатывает схему конвертации и определяет таблицы, в которые нужно вставить данные XML. Затем она заносит данные XML в реляционные таблицы.

    Т.к. исходный документ XML может быть большим, весь документ не читается в память для выполнения bulk загрузки. Вместо этого bulk загрузка представляет данные XML в виде потока и читает его. Когда утилита читает данные, она определяет таблицы базы данных, создает нужные записи из источника данных XML и после этого отправляет записи в SQL Server для вставки.

    Для дополнительной информации о работе и использовании bulk загрузки смотрите Выполнение bulk загрузки данных XML.


    Методы доступа к данным SQLXML

    По сравнению с SQL Server 2000 были добавлены два новых способа использования функциональности SQLXML:

    • Управляемые классы SQLXML

    • Сетевые службы SQLXML

    Кроме того, доступ HTTP к SQL Server был улучшен для обеспечения поддержки апдейтаграмм в шаблонах.

    Управляемые классы SQLXML

    Управляемые классы SQLXML обеспечивают функциональность SQLXML 3.0 в Microsoft .NET Framework. Используя управляемые классы SQLXML, Вы можете написать приложение C# для того, чтобы получить доступ к данным XML из экземпляра SQL Server, вытащить данные в среду .NET Framework, обработать их и отправить обновления обратно в SQL Server.

    Для дополнительной информации об использовании управляемых классов SQLXML смотрите Поддержка SQLXML .NET.


    Сетевые службы SQLXML

    Поддержка сетевых служб в SQLXML представляет SQL Server в виде сетевой службы, которая предлагает функциональность SQL Server клиентам. Вы можете отправлять запросы SOAP HTTP на сервер, на котором работает SQLXML, для выполнения хранимых процедур, пользовательских функций (UDFs) и шаблонов.

    Сетевые службы также устанавливаются с помощью IIS Virtual Directory Management в утилите SQL Server. Когда Web Services Virtual Directory установлена, Вы можете добавлять хранимые процедуры и шаблоны на Ваш сайт. Клиенты могут после этого получать доступ к этим службам по HTTP через протокол SOAP.

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

    Для дополнительной информации о сетевых службах SQLXML смотрите Поддержка сетевых служб (SOAP) в SQLXML.


    XQuery в .NET Framework 2.0

    Чтобы дополнить появление XQuery в SQL Server 2005, процессор XQuery среднего уровня встроен в пространство имен System.Xml.Query в релизе .NET Framework V2.0 в Visual Studio 2005 Beta. В этой главе мы покажем, как это дает возможность выполнять запросы и объединять различающиеся источники данных, такие, как файлы и реляционные данные, хранимые в азах данных SQL Server.

    Ниже дан самый простой пример кода запроса, использующегося для выборки всех книг в книжном магазине, которые имеют свойство литературного стиля - автобиография и вывода названий книг в виде нового магазина. Загружаемый локальный файл называется "books.xml", а результаты выполнения запроса сохраняются в другой локальный файл с названием "output.xml".

    
    using (XmlWriter writer = XmlWriter.Create("output.xml"))
    {
    XQueryCommand xq = new XQueryCommand();
       string query =
             "<bookstore>" +
             "{ for $s in /bookstore/book " +
             "where $s/@genre='autobiography' " +
             "return $s/title }" +
             "</bookstore>";
       xq.Compile(query);
       xq.Execute("books.xml", new XmlUrlResolver(), writer);
    }
    

    Ниже показан запрос:

    
    <bookstore>
    {for $s in /bookstore/book
    where $s/@genre='autobiography'
    return $s/title}
    </bookstore>
    

    Класс XQueryCommand - это процессор XQuery. Запрос сначала компилируется методом Compile, которые выполняет проверку типа значений и генерирует исполнимый код. Метод Execute выполняет запрос, используя в качестве входных данных документ books.xml.

    Класс XQueryCommand также может выполнять запросы по данным в реляционных таблицах в SQL Server с возможностью встроенных команд T-SQL в выражении XQuery. В результате это позволяет интегрировать два различных языка запросов, работающих в разных доменах, и дополняет SQL Server 2005, где команда XQuery встроена в команду T-SQL. В показанном ниже коде запрос используется для выборки всех клиентов из тестовой базы данных Northwind.

    
    declare namespace sql='http://schemas.microsoft.com/framework/2003/xml/sql';
    <Customers>{
    $for $customer in sql:query("select * from customers", "conn")/*
    return customer
    }</Customers>
    

    Метод sql:query позволяет Вам выполнить запрос T-SQL, результаты которого возвращаются в виде документа XML в том же виде, что и у функции XQuery doc(). Если результат состоит из реляционных типов, то он конвертируется в XML на клиенте в виде эффективного потока. Если результаты запроса SQL уже являются данными XML, например, в случае запроса FOR XML или запроса данных XML, то используется результат запроса. Если результат не возвращается, как в случае большинства команд T-SQL DML, то этот результат обрабатывается как пустой документ, т.е. это не воспринимается как ошибка. Ниже показан результат этого XQuery, который выводит всех клиентов из таблицы клиентов, обрамленных в элемент Customers. Элемент строки автоматически создается для каждой строки таблицы.

    
    <Customers>
      <row>
        <CustomerID>ALFKI</CustomerID>
        <CompanyName>Alfreds Futterkiste</CompanyName>
        <ContactName>Maria Anders</ContactName>
        <ContactTitle>Sales Representative</ContactTitle>
        <Address>Obere Str. 57</Address>
        <City>Berlin</City>
        <PostalCode>12209</PostalCode>
        <Country>Germany</Country>
        <Phone>030-0074321</Phone>
        <Fax>030-0076545</Fax>
      </row>
      <row>
        <CustomerID>ANATR</CustomerID>
        <CompanyName>Ana Trujillo Emparedados y helados</CompanyName>
        <ContactName>Ana Trujillo</ContactName>
        <ContactTitle>Owner</ContactTitle>
        <Address>Avda. de la Constitucion 2222</Address
        <City>Mexico D.F.</City
        <PostalCode>05021</PostalCode>
        <Country>Mexico</Country>
        <Phone>(5) 555-4729</Phone>
        <Fax>(5) 555-3745</Fax>
      </row>
    ...
    </Customers>
    

    Чтобы выполнить этот запрос в SQL Server, используется следующий код.

    
    static String ConnectionString = "database=Northwind;
       Data Source=localhost;Integrated Security=SSPI";
    
    using (SqlConnection connection = new SqlConnection(ConnectionString))
    {
           XmlDataSourceResolver resolver = new XmlDataSourceResolver();
       resolver.Add("conn", connection);
       XQueryCommand xq = new XQueryCommand();
       
    StreamReader reader = new StreamReader("query.xml");
       xq.Compile(reader);
       
    XmlWriterSettings settings = new XmlWriterSettings();
       settings.Indent = true;
       settings.ConformanceLevel = ConformanceLevel.Auto;
       using (XmlWriter writer =
          XmlWriter.Create("output.xml", settings))
       {
          try
          {
             connection.Open();
             xq.Execute(resolver, writer);
          }
          catch (Exception e)
          {
             Console.Out.WriteLine(e.Message);
             Console.Out.WriteLine(e.InnerException.Message);
          }
       }
    }
    

    Этот класс XmlDataSourceResolver играет роль связывания соединения базы данных с именем, которое может быть использовано в вызове sql:query. Запрос читается из локального файла query.xml, компилируется, и создается XmlWriter для записи результатов. Заметьте, что установка ConformanceLevel.Auto используется в XmlWriter, который автоматически определяет, что создано - фрагмент или документ, и, благодаря возможности конструировать элементы в результате, XQuery может генерировать и фрагмент, и документ. Перед выполнением запроса открывается соединение к базе данных, выполняется запрос и результаты записываются в файл.

    Команда sql:query очень гибкая и мощная из-за возможности поддерживать именованные параметры в запросе T-SQL и вызывать хранимые процедуры на сервере. Именованные параметры в sql:query работают так же, как классы System.Data.SqlClient. Параметр передается в запрос T-SQL, обозначаемый как "@" и имя. Привязка между этим именем и действительным значением далее передается в виде параметра в запрос. Для каждого именованного параметра соответствующее значение (определяемое позицией в последовательности) используется для привязки. Количество имен параметров должно совпадать с количеством привязок языка. Лучше всего это представлено в следующем примере:

    
    declare namespace sql='http://schemas.microsoft.com/framework/2003/xml/sql';
    let $country := "USA"
    <Customers>{
    for $customer in sql:query("select * from customers where Country = @country",
    "conn", {"@country"}, {$country})
    return $customer/PostalCode
    }</Customers>
    

    В этом случае параметр country передается в запрос T-SQL, связывая переменную XQuery $country с параметром @country. Результатом является список всех почтовых индексов клиентов в США.

    Функция sql:query также может использоваться для вызова хранимой процедуры T-SQL, передавая параметры описанным выше путем, если это необходимо. Показанный ниже пример демонстрирует, как вызвать хранимую процедуру "Ten Most Expensive Products" из базы данных Northwind, которая не имеет входных параметров.

    
    declare namespace sql ='http://schemas.microsoft.com/framework/2003/xml/sql';
    for $prod in sql:query('Exec "Ten Most Expensive Products"', "conn")
    return $prod
    

    Заключение

    В этой статье описываются технологии, связанные с XML в SQL Server 2005. Особенности серверной стороны включают встроенное преобразование для хранения XML, индексирование и обработку запросов. Существующие особенности, такие, как FOR XML и OpenXML, также были улучшены. Поддержка клиентской стороны содержит улучшения в ADO.NET для поддержки данных типа XML и улучшения в System.Xml для поддержки XQuery для выполнения запросов на различных источниках данных XML. Кроме того, улучшения в технологии конвертации SQLXML теперь встроены в SQL Server 2005.

    Поддержка серверной и клиентской стороны полезна для разных случаев. Тип XML обеспечивает простой механизм хранения данных XML через вставку данных XML в нетипизированный столбец XML. Использование схем XML для определения типизированного XML помогает ядру базы данных оптимизировать хранение этих данных и выполнение запросов помимо обеспечения проверки данных.

    Тип XML сохраняют порядок документа и полезны для таких приложений, как приложения документооборота. Этот тип также может обрабатывать рекурсивные схемы XML. Реляционная модель данных и сейчас является лучшим выбором для структурированных данных с известной схемой. Даже [n]varchar(max) подходит для случаев, когда выполнение запросов и обновление не так важны.

    Технология конвертации SQLXML полезна, когда Вы хотите использовать модель программирования на основе XML, с реляционными данными, хранящимися в таблицах на сервере. Конвертация основана на определении схемы XML в виде представления XML. Конвертация может быть использована для bulk загрузки данных XML в таблицы и для выполнения запросов по таблицам, используя XPath 1.0. Порядок документа при этом не сохраняется, поэтому технология конвертации полезна для обработки данных XML, в противоположность обработке документов XML.

    Основные классы XML в System.Xml в будущем релизе .NET Framework V2.0 Beta 1 позволят Вам читать, записывать, перемещать и изменять XML. С улучшениями в производительности, типизировании и выполнении запросов поддержка XML в релизе V2.0 продолжает лидировать в инновациях, поддержке стандартов и простоте использования. Эта поддержка также включает процессор XQuery для управления источниками XML вне SQL Server.

    Технологии серверной и клиентской стороны дополняют друг друга. Технология конвертации может усилить возможности серверной стороны, такие, как поддержка порядка документа и рекурсивные схемы, и найти больше применения в приложениях. С другой стороны, CLR расширяет возможности существующих инструментов XML, таких, как трансформация XSLT в данные XML. Обработки XQuery на сервере и на клиенте сильно связаны между собой, а также со спецификацией XQuery от ноября 2003 года. Обработки схем XML на серверном и среднем уровнях также сильно связаны.

    Shankar Pal - Program Manager ядра SQL Server, работающий в области технологий XML на стороне сервера.

    Mark Fussell - ведущий Program Manager в команде WebData в Microsoft, которая разрабатывает технологии доступа к данным, включая компоненты в пространствах имен System.Xml и System.Data в .NET Framework, Microsoft XML Core Services (MSXML) и Microsoft Data Access Components (MDAC). Его адрес: http://weblogs.asp.net/mfussell.

    Комментариев нет:

    Отправить комментарий