XML в MS SQL Server 2000 и технологиях доступа к данным
Страница 10. XML-шаблоны как разновидность хранимых процедур


XML-шаблоны как разновидность хранимых процедур

Шаблоны (templates) объединяют в себе квантово-волновой (SQL / XML) дуализм SQL Server. Козьма Прутков мог бы смело их уподобить хранимым процедурам, которые допускают как SQL-, так и XPath-запросы. Шаблон - это XML-файл, структура которого показана на рис.6.


<?xml version="1.0" encoding="utf-8" ?>
<Солянка xmlns:sql="urn:schemas-microsoft-com:xml-sql">
<sql:header>
<sql:param name="Колво"></sql:param>
<sql:param name="Сумма">1000</sql:param>
</sql:header>
<sql:query client-side-xml="0">

SELECT TOP 1 * FROM Employees FOR XML AUTO
</sql:query>
<sql:query client-side-xml="1">

SELECT c.ContactName, COUNT(o.OrderDate) AS 'Кол-во'
FROM Customers c INNER JOIN Orders o ON c.CustomerID = o.CustomerID
GROUP BY c.ContactName HAVING COUNT(o.OrderDate) >= @Колво
FOR XML NESTED
</sql:query>
<sql:xpath-query mapping-schema="..\Schemas\SQLSchema1.xsd">

Клиент[number(Заказы/Заказ/Стоимость)>$Сумма]
</sql:xpath-query>
<sql:xpath-query mapping-schema="..\Schemas\SQLSchema2.xsd">

Сотрудник
</sql:xpath-query>
</Солянка>

 

Рис.6

Он состоит из частей трех основных типов. Каждая часть является опциональной. В <sql:query> перечисляются операторы SQL, в <sql:xpath-query> - запросы XPath, в <sql:header> описываются параметры для запросов (как SQL, так и XPath). Привязка описаний параметров в заголовке к параметрам в запросах осуществляется при помощи атрибута name ("Колво" - @Колво, "Сумма" - $Сумма). В одной секции <sql:query> может находиться несколько SQL-запросов, в отличие от XPath-запросов, каждый из которых должен заключаться в свою секцию <sql:xpath-query>. В данном примере SQL-запросы пришлось разнести по разным секциям, так как первый из них выполняется на сервере, а второй - на клиенте. Атрибут client-side-xml эквивалентен свойству ClientSideXml класса SqlXmlCommand, с которым мы сталкивались в п.6. В <sql:query> могут присутствовать не только select'ы, но и операторы объявления и модификации данных, а также вызовы хранимых процедур, что позволяет помещать в секцию не просто несколько разрозненных операторов, а последовательность, связанную логикой выполнения. Условие - весь select-вывод должен идти в виде XML. Допускаются опции AUTO и EXPLICIT. XPath-запросы выполняются относительно заданной в атрибуте mapping-schema аннотированной схемы. Для каждого XPath-запроса она может быть своя. Отметим, что некоторые (хоть все) из задействованных аннотированных схем могут располагаться непосредственно в файле шаблона, так что предыдущий шаблон можно записать как:


<?xml version="1.0" encoding="utf-8" ?>
<Солянка xmlns:sql="urn:schemas-microsoft-com:xml-sql">
<xs:chema xmlns:xs="https://www.w3.org/2001/XMLSchema"
_ xmlns:ms="urn:schemas-microsoft-com:mapping-schema"
id="SQLSchema2" sql:is-mapping-schema="1">

...Схема с рис.5...
</xs:schema>

...<sql:header> и <sql:query>-секции с рис.6...
<sql:xpath-query mapping-schema="..\Schemas\SQLSchema1.xsd">

Клиент[number(Заказы/Заказ/Стоимость)>$Сумма]
</sql:xpath-query>
<sql:xpath-query mapping-schema="#SQLSchema2">

Сотрудник
</sql:xpath-query>
</Солянка>

 

Рис.7

Таким образом, результат выполнения шаблона может состоять из фрагментов различных схем, соответствующих разным секциям, объединенных корневым элементом. Остается сохранить его в файле формата UTF-8 (Скрипт 11).


static void Execute_TemplateFile_SQLXML()
{
...
cmd.CommandText = "..\\Templates\\XMLTemplate1.xml";
cmd.CommandType = SqlXmlCommandType.TemplateFile;
SqlXmlParameter prm = cmd.CreateParameter();
prm.Name = "@Колво"; prm.Value = 20;
XmlDocument xml = new XmlDocument();
xml.Load(cmd.ExecuteStream());
...
}

 

Скрипт 11

Вызывающее приложение передает шаблону только один параметр @Колво = 20 (показать клиентов и количество сделанных ими заказов, если оно превышает 20). Для другого запроса будет взято значение параметра по умолчанию из шаблона - <sql:param name="Сумма">1000</sql:param> (показать только тех клиентов, которые сделали хотя бы один заказ на сумму свыше 1000). Если приложение не обеспечивает параметра при вызове шаблона и секция <sql:header> не содержит значение параметра по умолчанию, то для него будет использовано значение по умолчанию, определенное в схеме SQL Server (DEFAULT для поля таблицы или для параметра хранимой процедуры). Если значение по умолчанию в схеме SQL Server также не определено, значение параметра полагается в NULL. Стоит обратить внимание на конвертацию number(Заказы/Заказ/Стоимость) в одном из XPath-запросов в шаблонах рис.6, 7. Дело в том, что несмотря на объявление стоимости как xs:type="xs:float" параметр $Сумма норовит передаваться как nvarchar, что приводит к неверным результатам (напр. '5.00' > '1000'). Еще один, эквивалентный, способ вызова шаблона из SqlXml состоит в использовании свойства CommandStream вместо CommandText. Соответственно должно быть скорректировано свойство CommandType.

...
cmd.CommandStream = new FileStream("..\\Templates\\XMLTemplate1.xml", FileMode.Open, FileAccess.Read);
cmd.CommandType = SqlXmlCommandType.Template;
...

Или даже так:


...
cmd.CommandStream = new MemoryStream();
StreamWriter sw = new StreamWriter(cmd.CommandStream, System.Text.Encoding.UTF8);
sw.Write("<?xml version='1.0' encoding='utf-8' ?> " +
"<Солянка xmlns:sql='urn:schemas-microsoft-com:xml-sql'>" +


...Содержание шаблона с рис.6...


"</Солянка>");
sw.Flush(); cmd.CommandStream.Position = 0;
cmd.CommandType = SqlXmlCommandType.Template;
...

В свойстве XslPath класса SqlXmlCommand может задаваться ссылка на XSL-преобразование, которому подвергается сформированный на основе шаблона XML-файл. Преобразование можно также оговорить в корневом элементе шаблона (например, sql:xsl="....xsl">).

Для повышения производительности применяется кэширование шаблонов, что означает, что они не выгружаются из памяти после первого выполнения. Емкость кэша (в штуках) задается в HKLM\SOFTWARE\Microsoft\MSSQLServer\Client\SQLXML3\TemplateCacheSize и по умолчанию равна 31. Чтобы запретить кэширование, необходимо зайти в закладку Advanced свойств виртуальной директории SQL Server (см. п.13) и отметить Disable Caching of template. Аналогично настраивается кэширование аннотированных схем (HKLM\SOFTWARE\Microsoft\MSSQLServer\Client\SQLXML3\SchemaCacheSize).

 
« Предыдущая статья   Следующая статья »