XML в MS SQL Server 2000 и технологиях доступа к данным Страница 10. XML-шаблоны как разновидность хранимых процедур
|
Страница 10 из 15
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). |