Смекни!
smekni.com

Использование XML совместно с SQL (стр. 6 из 8)

Тип команды Значение в ADO
Запрос Transact-SQL {C8B522D7-5CF3-11CE-ADE5-00AA0044773D}
Запрос XPath {EC2A4293-E898-11D2-B1B7-00C04F680C56}
Запрос в XML-шаблоне {5D531CB2-E6Ed-11D2-B252-00C04F681B71}
Поведение провайдера по умолчанию {C8B521FB-5CF3-11CE-ADE5-00AA0044773D}

Так как результат выполнения объекта Command теперь не всегда может иметь реляционный характер, его нельзя помещать в объект Recordset. Название нового стандартного свойства Output Stream говорит само за себя: результат выполнения объекта Command может быть сохранен в потоке (любом объекте, поддерживающим интерфейс IStream). Кроме этого, поскольку запрос (свойство CommandText) теперь может представлять собой запрос XPath, нужно как-то задать аннотированную схему для него. Это делается с помощью стандартного свойства Mapping Schema. Пора переходить к примерам.

Использование Command для формирования XML-документа на сервере

В этом примере показано, как сформировать XML-документ на сервере и отправить его клиенту с использованием ADO:

<%' Определяемконстанты ADO.Const adopenStatic = 3Const adLockReadOnly = 1Const adCmdText = 1Const adPersistXML = 1Const adExecuteStream = &H400' созданиеобъектовDim cmd,connSet cmd = Server.CreateObject("ADODB.Command")Set conn = Server.CreateObject("ADODB.Connection")conn.Provider = "sqloledb"conn.Open "Data Source=server;Initial catalog=pubs;", "user", "password"Set cmd.ActiveConnection = conncmd.CommandType = adCmdTextcmd.CommandText = "select au_fname, au_lname, address " _ & "from authors where au_fname like 'M%' for xml auto"cmd.Properties("Output Stream") = Responsecmd.Properties("xml root") = "root"cmd.Execute , , adExecuteStreamSet cmd = nothingSet conn = nothing%>

Здесь используется встроенная инструкция FOR XML AUTO для формирования XML-документа на SQL Server’е. В результирующем документе отсутствует корневой элемент, и для его указания используется еще одно стандартное свойство – xml root. В качестве выходного потока был использован объект Response. Результат обращения к этой ASP-страничке вы, наверное, уже давно выучили наизусть: это будет XML-документ с именами, фамилиями и адресами авторов.

Выполнение шаблона

Возьмем шаблон из первого примера раздела «Шаблоны» (код на ASP):

<%' Нужно указать это:Response.ContentType = "text/xml"' Определяем константы ADO.Const adCmdText = 1Const adExecuteStream = &H400' СоздаемобъектыDim cmd,connSet cmd = Server.CreateObject("ADODB.Command")Set conn = Server.CreateObject("ADODB.Connection")conn.Provider = "sqloledb"conn.Open "Data Source=server;Initial catalog=pubs;", "user","password"' ШаблонDim ss = "<?xml version='1.0' ?>" & _ "<my_root xmlns:sql='urn:schemas-microsoft-com:xml-sql'>" & _ "<sql:query>" & _ "select au_fname,au_lname,address from authors " & _ "where au_fname like 'M%' for xml auto" & _ "</sql:query>" & _ "</my_root>"Set cmd.ActiveConnection = conncmd.CommandType = adCmdTextcmd.CommandText = s' Диалектшаблонаcmd.Dialect = "{5D531CB2-E6Ed-11D2-B252-00C04F681B71}"cmd.Properties("Output Stream") = Responsecmd.Execute , , adExecuteStreamSet cmd = nothingSet conn = nothing%>

Выполнение запроса XPath

С помощью ADO также можно выполнять запросы XPath, правда, пока только на аннотированных XDR-схемах. Вот скрипт на vbs, выполняющий такой запрос:

' Определяем константы ADO.Const adCmdText = 1Const adExecuteStream = &H400' СозданиеобъектовDim cmd,conn,cmdStreamDim ie Set ie = CreateObject("InternetExplorer.Application")ie.Navigate "about:blank"Set cmd = CreateObject("ADODB.Command")Set conn = CreateObject("ADODB.Connection")Set cmdStream = CreateObject("ADODB.Stream")conn.Provider = "sqloledb"conn.Open "Data Source=server;Initial catalog=pubs;", "user", "password"cmdStream.OpenSet cmd.ActiveConnection = conncmd.CommandType = adCmdText' XPath-запросcmd.CommandText = "Авторы"' Диалект XPath cmd.Dialect = "{EC2A4293-E898-11D2-B1B7-00C04F680C56}"cmd.Properties("Base Path") = "C:&bsol;Inetpub&bsol;wwwroot&bsol;server_pubs"cmd.Properties("Output Stream") = cmdStream' Аннотированнаясхемаcmd.Properties("Mapping Schema") = "schema&bsol;myschema.xml"' Шаблонтрансформацииcmd.Properties("XSL") = "&bsol;template&bsol;first_select.xsl"cmd.Properties("xml root") = "my_root"cmd.Execute , , adExecuteStreamDim strstr = cmdStream.ReadTextdoloop while ie.Busyie.Document.writeln CStr(str)ie.Document.closeie.visible = 1

Здесь я использовал новую аннотированную схему и шаблон трансформации.

Аннотированная схема:

<?xml version="1.0" encoding="windows-1251" ?><Schema xmlns="urn:schemas-microsoft-com:xml-data" xmlns:sql="urn:schemas-microsoft-com:xml-sql" xmlns:dt="urn:schemas-microsoft-com:datatypes"> <ElementType name="Авторы" sql:relation="authors"> <AttributeType name="Имя" dt:type="string" /> <AttributeType name="Фамилия" dt:type="string" /> <AttributeType name="Адрес" dt:type="string" /> <attribute type="Имя" sql:field="au_fname" /> <attribute type="Фамилия" sql:field="au_lname" /> <attribute type="Адрес" sql:field="address" /></ElementType></Schema>

Шаблон трансформации:

<?xml version="1.0" encoding="windows-1251" ?><xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> <xsl:template match = "*"> <xsl:apply-templates /> </xsl:template> <xsl:template match = "/"> <html> <body> <table border="1" style="table-layout:fixed" width="600"> <tr bgcolor="teal"> <th><font color="white">Имя</font></th> <th><font color="white">Фамилия</font></th> <th><font color="white">Адрес</font></th> </tr> <xsl:for-each select="my_root/Авторы"> <tr> <td><font color="teal"><xsl:value-of select="@Имя"/></font></td> <td><font color="teal"><xsl:value-of select="@Фамилия"/></font></td> <td><font color="teal"><xsl:value-of select="@Адрес"/></font></td> </tr> </xsl:for-each> </table> </body> </html> </xsl:template></xsl:stylesheet>

XML-документ на стороне клиента

Предположим, ваш SQL Server работает в очень напряженном режиме, и вы не хотите нагружать его еще больше, заставляя формировать XML-документы. Можно сделать так: создать обычный рекордсет и загрузить его в формате XML в объект DOMDocument или какой-либо другой. Решение на первый взгляд здравое, однако, поработав немного с таким документом, вы поймете, что это не то. Во-первых, структура такого XML-документа задается жестко без возможности изменения. Во-вторых, схема сохраняется в формате XDR, а он уже стар и может не удовлетворять вашим потребностям. К тому же возникают проблемы с выполнением шаблонов и XPath-запросами. Для решения этих (и многих других) проблем был создан новый сервисный провайдер – SQLXMLOLEDB. Как и другие сервисные провайдеры (например, MSDataShape) он предназначен только для преобразования результирующего набора строк в нужный формат. Так как SQLXMLOLEDB ничего не знает о форматах протоколов обмена данными с SQL-серверами, он использует для этого соответствующий провайдер. К сожалению, провайдер SQLXMLOLEDB пока умеет работать совместно только с SQLOLEDB-провайдером для SQL Server, однако в будущем (по крайней мере, я очень надеюсь) он сможет работать с другими провайдерами, например, MSDAORA (провайдер для Oracle). Если такая поддержка будет встроена, у нас будет возможность получать XML-документы от источников, которые не поддерживают XML напрямую.

В режиме форматирования XML-документа на клиенте можно использовать в запросе предикат GROUP BY и агрегатные функции, недоступные в режиме формирования XML-документа на сервере (в режиме FOR XML AUTO). Как и любой другой сервисный провайдер, SQLXMLOLEDB предоставляет свой синтаксис запросов. К счастью, он не так сложен, как, например, синтаксис провайдера MSDataShape и ограничивается, по существу, следующим:

Оператор Назначение
FOR XML RAW Аналогичен серверному FOR XML RAW
FOR XML NESTED Аналогичен серверному FOR XML AUTO
FOR XML EXPLICIT Аналогичен серверному FOR XML EXPLICIT

Архитектура формирования документов на клиентской стороне изображена на рисунке 1.

Рисунок 1.

Возможность Формирование на клиенте Формирование на сервере
Использование предиката GROUP BY и агрегатных функций совместно с FOR XML AUTO (NESTED) Да Нет
Возможность получения одновременно нескольких рекордсетов Нет Да
Задание имен элементов результирующего документа с помощью псевдонимов таблиц Нет Да

Другие отличия вы можете найти в MSDN. Давайте перейдем к примерам.

Шаблон с агрегатными функциями

Ниже приведен пример использования FOR XML NESTED и атрибута client-side-xml. Шаблон возвращает документ с названиями городов и количеством авторов в каждом городе. Атрибут client-side-xml устанавливается в 1, что говорит об использовании клиентского форматирования.

<?xml version="1.0" ?><my_root xmlns:sql="urn:schemas-microsoft-com:xml-sql"> <sql:query client-side-xml="1"> select count(*) as number_of_authors,city from authors group by city order by number_of_authors desc for xml nested </sql:query></my_root>

Формирование XML-документа на клиенте с помощью ADO

У объекта Command есть свойство ClientSideXML, которое позволяет формировать XML-документ на клиенте. Рассмотрим пример:

<%Const adCmdText = 1Const adExecuteStream = &H400Response.ContentType = "text/xml"' Creating the objectsDim conn,cmdSet conn = Server.CreateObject("ADODB.Connection")Set cmd = Server.CreateObject("ADODB.Command")conn.Provider = "sqlxmloledb"conn.Open "Data Source=server;Initial catalog=pubs;Data Provider=sqloledb", _ "user","password"Dim ss = "select count(*) as number_of_authors,city" & _ "from authors" & _ "group by city" & _ "order by number_of_authors desc" & _ "for xml nested"Set cmd.ActiveConnection = ccmd.Properties("ClientSideXML") = "True"cmd.CommandType = adCmdTextcmd.CommandText = scmd.Properties("Output Stream") = Responsecmd.Properties("xml root") = "root"cmd.Execute , , adExecuteStreamSet cmd = nothingSet conn = nothing%>

В качестве основного провайдера задан провайдер SQLXMLOLEDB. Провайдер SQL Server’а задается с помощью строки Data Provider=sqloledb. Чтобы указать, что используется клиентское форматирование, свойство ClientSideXML установлено в true. Следует заметить, что это свойство (т.е. клиентское форматирование) можно использовать только для типа adCmdText. При вызове хранимых процедур его устанавливать нельзя.

Апдейтаграммы и XML Bulk Load

В этом разделе мы рассмотрим способы изменения данных (удаление, добавление и правка) с помощью XML-документов. Какие достоинства у этого метода перед использованием SQL-инструкций непосредственно в шаблоне? Во-первых, апдейтаграммы намного понятнее простым пользователям или неосведомленным программистам. Хотя синтаксис написания апдейтаграмм не так уж и прост, он подчиняется обычным правилам XML и, если вы совсем не разбираетесь в SQL, апдейтаграммы – лучший выбор. Кроме этого, вы просто не имеете другой столь же эффективной альтернативы, как XML Bulk Load для загрузки больших, очень больших объемов XML-данных. Но обо всем по порядку.