Лекция 10 (базы данных) 2

advertisement
Кафедра «ОСУ»
Весенний семестр 2010/2011 уч. года
Языки описания информации
Лекция ХХХ.
Работа с XML данными в
реляционных СУБД
Использование XML документов
• XML документы используются для описания
информации.
• Они могут использоваться для хранения и
обработки.
– в документах файловой системы;
– в базах данных (в поля записей).
• Обработка:
– обработка в программе;
– обработка с помощью процессоров (XSLT процессор,
XQuery процессор);
– передача в сообщениях.
Зачем хранить XML-данных в SQL
сервере
• Требуется эффективно распространять, запрашивать
и изменять свои XML-данные на основе транзакций.
– Большое значение имеет высокая детализация доступа к
данным.
– Например, иногда нужно извлекать некоторые разделы
XML-документа или вставлять в него новые разделы без
замены всего документа.
• Необходимо совместно использовать как
реляционные, так и XML-данные, и обеспечить их
совместимость в приложении.
• Необходима единая языковая поддержка запросов и
модификации данных в различных приложениях.
Зачем хранить XML-данных в SQL
сервере (2)
• Требуется, гарантировал правильность структуры данных
(выполнение проверки данных в соответствии с XML-схемами).
• Требуется индексировать XML-данные для оптимизации обработки
запросов и улучшения масштабируемости и использовать
эффективный оптимизатор запросов.
• Требуется обращаться к XML-данным, используя технологии SOAP,
ADO.NET и OLE DB.
• Требуется использовать для управления XML-данными средства
администрирования, реализованные в сервере баз данных.
– Примерами таких задач управления могут служить резервное
копирование данных, их восстановление и репликация.
• Если ни одно из этих условий не выполняется, то для хранения
данных лучше использовать тип данных отличный от XML,
например типы данных для хранения больших объектов
(например, [n]varchar(max) или varbinary(max)).
Поддержка работы с XML
в СУБД SQL Server
• Для поддержки новых требований к обработке данных,
Microsoft добавил в SQL Server возможности работы с
XML данными начиная с SQL Server 2000.
• SQL Server 2008 предоставляет следующие
возможности работы с XML:
– поддержка нового типа данных “xml”;
– поддержка запросов XQuery;
– возможность указывать запросы XQuery к XML-данным,
хранящимся в столбцах и переменных типа «xml»;
– возможность выполнять массовую загрузку XML-данных с
помощью расширенной инструкции OPENROWSET,
позволяющие ;
– расширения в предложении FOR XML и функции OPENXML,
впервые реализованные в SQL Server 2000.
Поддержка работы с XML
в SQL Server 2008
• Поддержка работы с XML в SQL Server 2008
может быть разделена на три большие
категории:
– возможности формировать XML документы (из
реляционных данных);
– возможности выполнять грамматический
разбор и запросы к XML документам,
хранящимся в XML полях;
– возможности выполнять проверку XML
документов.
Варианты хранения XML-данных
SQL Server поддерживает несколько вариантов хранения
XML-данных.
– Хранение в виде XML типа данных.
– Сочетание XML типов данных и реляционном данных.
– Хранение XML данных в виде больших
объектов, [n]varchar(max) и varbinary(max).
– Гибридная модель
• Обычно используется сочетание этих подходов.
– Например, XML-данные можно сохранить в столбце
типа xml, производя продвижение его свойств до уровня
реляционных столбцов.
– Либо можно использовать технологию сопоставления для
хранения нерекурсивных фрагментов в столбцах, отличных
от XML, а в столбцах типа xml хранить только рекурсивные
фрагменты.
Хранение в виде типа данных XML.
• Данные при этом хранятся во внутреннем представлении, которое
обеспечивает неизменность XML-содержимого данных.
• Это внутреннее представление включает в себя сведения об
иерархии контейнеров, порядке документов и значений элементов
и атрибутов.
• Точнее говоря, при этом обеспечивается неизменность InfoSetсодержимого XML-данных.
• InfoSet-содержимое не всегда идентично текстовым XML-данным,
потому что следующая информация при этом не сохраняется:
несущественные пробелы, порядок атрибутов, префиксы
пространств имен и XML-декларация.
• Для типизированного (то есть связанного с XML-схемой) типа
данных xml модуль проверки после обработки схемы (PSVI)
добавляет в информационный набор данные о типах и кодирует их
во внутреннее представление. Это значительно ускоряет
синтаксический анализ.
Хранение XML данных в виде
больших объектов
• XML данных можно хранить в виде больших
объектов в полях типа [n]varchar(max) и
varbinary(max).
• При этом хранится идентичная копия данных.
• Это полезно в приложениях специального
назначения, например в приложениях,
обрабатывающих юридическую документацию.
• Большинству приложений точная копия данных
не нужна — им хватает XML-содержимого
(правильности элементов InfoSet).
Сочетание XML типов данных и
реляционном данных
• Используя аннотированную схему (AXSD),
можно разбить XML на столбцы одной или
нескольких таблиц.
• Это обеспечивает правильность данных на
реляционном уровне.
• В результате гарантируется сохранность
иерархической структуры данных, хотя
порядок элементов не учитывается.
• Схема не может быть рекурсивной.
Технология XML View
• Путем определения взаимосвязи между XML
схемами и таблицами в БД можно создать
"XML view" имеющихся реляционных данных.
• Для ввода данных в используемые XML view
таблицы может использоваться массовая XML
загрузка.
• Можно выполнять запросы к XML view с
помощью XPath; такой запрос транслируется в
SQL запросы к таблицам.
• Аналогично обновления также
распространяются по всем таблицам.
Достоинства технологии XML View
• Технология XML-view полезна в следующих ситуациях:
– Нужна программная модель ориентированная на XML для
работы с существующими реляционными данными.
– Имеется схема (XSD, XDR) для XML данных, которую
предоставил внешний партнер.
– Порядок в данных не важен, или запросы к данным в
таблицах не являются рекурсивными, или максимальная
глубина рекурсии известна заранее.
– Требуется выполнять запросы и изменять данные с
помощью XML view, используя XPath.
– Нужна массовая загрузка XML данных и их декомпозиция
на нижележащие таблицы, с помощью XML view.
• Например, реляционные данные представляются в
виде XML данных для обмена данными и работы Web
сервисов, и XML данные имеют фиксированную схему.
Пример: моделирование данных с помощью
аннотированной XML Schema (AXSD)
• Предположим, что имеются следующие данные,
которые хотелось бы обрабатывать, как XML данные:
– customers (клиенты),
– orders (заказы) и
– товары заказов (line items),
• Для этого нужно:
– Описать XML view используя AXSD над реляционными
данными.
– XML view позволяет выполнять массовую загрузку XML
данных в таблицы, выполнять запросы и обновления
реляционных данных с помощью XML view.
– Такая модель является полезной, если требуется
обмениваться данными, содержащими XML разметку, с
другими приложениями, и при этом не нарушать работу
уже имеющихся SQL приложений.
• Взаимосвязь между XML и реляционным хранилищем выполняется с
помощью аннотированных схем (annotated schema, AXSD),
• XML данные делятся по колонкам одной или нескольких таблиц. Это
сохраняет поддержку XML данных на реляционном уровне.
• В результате этого, сохраняется иерархическая структура, хотя порядок
следования элементов игнорируется.
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:sql="urn:schemas-microsoft-com:mapping-schema">
<xsd:element name="Employee" sql:relation="Employees" >
<xsd:complexType>
<xsd:sequence>
<xsd:element name="FName" sql:field="FirstName” type="xsd:string" />
<xsd:element name="LName“ sql:field="LastName“ type="xsd:string" />
</xsd:sequence>
<xsd:attribute name="EmpID“ sql:field="EmployeeID“ type="xsd:integer" />
</xsd:complexType>
</xsd:element>
</xsd:schema>
Гибридная модель
• Часто для моделирования данных
подходящей является комбинация колонок с
реляционными и xml типами данных.
– Некоторые из значений из XML данных могут быть
сохранены в реляционных колонках, а оставшиеся
или все XML значение может быть сохранено в
XML колонке.
– Это может дать лучшую производительность, так
как при использовании реляционных колонок
имеется больше контроля над индексами и
параметрами связывания.
Гибридная модель (2)
• Какие значения хранить в реляционных колонках
зависит от степени их использования (workload).
– Например, если все XML значения получаются с
использованием XPath выражения (например,
/Customer/@CustId), то перенос значения атрибута CustId в
реляционную колонку и ее индексирование, может
повысить скорость обработки запросов.
– С другой стороны, если значительную часть XML данных
неизбыточно декомпозировать в реляционные колонки, то
значительно увеличатся и затраты на их сборку (reassembly).
• Для сильно структурированных XML данных, например,
если содержание таблицы было конвертировано в XML;
то можно отобразить все значения в реляционные
колонки и можно использовать технологию XML view.
Названия таблиц
• В СУБД используются схемы:
• <имя БД>.<схема1> … <схемаN>.<название таблицы>
Формат XML может использоваться
только как формат вывода данных
• Формат XML может использоваться только, как
временный формат вывода данных, полученных
из реляционных данных с помощью FOR XML.
• Такой подход применяется в таких сценариях,
когда реляционные таблицы содержат текущие
данные, а XML формат создается только для их
чтения приложениями, например, для
отображения динамических web страниц.
• В таком сценарии, XML просто предоставляет
независимые от СУБД, легкие для
преобразования представления данных.
XML данные могут сохраняться в
реляционных колонках
• XML can be stored in relational (nvarchar and
so on) columns.
• This might be the best option when your XML
is sometimes not well formed or when the
learning curve to XQuery is too high for an
application-delivery time frame.
• This is also a valuable option when the bytefor-byte exactness of the XML must be
preserved.
XML данные могут сохраняться в колонках
специального типа данных XML
• XML данные могут хранится, как не
типизированный XML, т.е. XML хранится в
колонках типа «xml data» без использования
коллекции схем.
Расширение FOR XML для
оператора SELECT
Формирование XML данных с
помощью FOR XML
• Можно выполнять запросы SQL,
возвращающие результаты в формате XML, а
не в виде стандартных наборов строк.
• Такие запросы могут выполняться как
напрямую, так и из хранимых процедур или
пользовательских функций.
• Для получения результатов напрямую сначала
необходимо использовать предложение FOR
XML инструкции SELECT. Затем необходимо
задать режим XML внутри предложения FOR
XML: RAW, AUTO, EXPLICIT или PATH.
Формирование XML документов
• В языке T-SQL к оператору SELECT добавлены
новые ключевые слова FOR XML, который
преобразует результаты запроса SELECT в XML
формат.
• Директивы AUTO, RAW, EXPLICIT и PATH позволяют
управлять структурой формируемого XML
документа;
• Оператор FOR XML совместно с директивами
RAW, AUTO, PATH и EXPLICIT позволяет
генерировать XML документы, удовлетворяющие
почти всем требованиям языка XML.
Использование AUTO, RAW, EXPLICIT
и PATH
• Директивы AUTO, RAW, EXPLICIT и PATH позволяют
управлять структурой формируемого XML документа;
– использование директив AUTO и RAW позволяет формировать
XML документ, содержащий XML элемент для каждой строки в
результате выборки. Они имеют простой синтаксис и их просто
использовать, но они предоставляют мало возможности
управлять структурой получаемого XML документа.
– использование директивы EXPLICIT предоставляет больше
возможностей по управлению структурой создаваемых XML
данных, но при этом используется намного более сложный
синтаксис и многие пользователи считают, что его трудно
использовать;
– директива PATH имеет более простой синтаксис и мощные
возможности настройки. Почти все, что возможно сделать с
помощью директивы EXPLICIT также возможно и с помощью
директивы PATH.
• Например, следующая инструкция SELECT получает данные
из таблиц Sales.Customer и Sales.SalesOrderHeader базы
данных AdventureWorks2008R2.
• В этом запросе задается режим AUTO в предложении FOR
XML:
USE AdventureWorks2008R2
GO
SELECT Cust.CustomerID, OrderHeader.CustomerID,
OrderHeader.SalesOrderID, OrderHeader.Status
FROM Sales.Customer Cust
INNER JOIN Sales.SalesOrderHeader OrderHeader
ON Cust.CustomerID = OrderHeader.CustomerID
FOR XML AUTO
Режим RAW
• Запись в конце SELECT оператора ключевых слов FOR XML RAW говорит
SQL Server генерировать XML документ имеющий структуру: один-XMLэлемент-для-записи.
• Утверждение FOR XML имеет несколько опций, которые меняют
получаемый XML результат от фрагмента XML документа, до well-formed
документов с немного (в сравнении с несколькими другими опциями FOR
XML) измененной структурой.
• Синтаксис записи :
FOR XML RAW [ (’ElementName’) ]
[
[ , BINARY BASE64 ]
[ , TYPE ]
[ , ROOT [ (’RootName’) ]
]
[ , { XMLDATA | XMLSCHEMA [ (’TargetNameSpaceURI’) ]} ]
[ , ELEMENTS [ XSINIL | ABSENT ]
]
SELECT Name, ListPrice, Color
FROM Production.Product [Product]
WHERE Name LIKE ‘%Chain%’
ORDER BY Name
FOR XML RAW
Go
<row Name=”Chain” ListPrice=”20.2400” Color=”Silver” />
<row Name=”Chain Stays” ListPrice=”0.0000” />
<row Name=”Chainring” ListPrice=”0.0000” Color=”Black” />
<row Name=”Chainring Bolts” ListPrice=”0.0000”
Color=”Silver” />
<row Name=”Chainring Nut” ListPrice=”0.0000”
Color=”Silver” />
SELECT [PurchaseOrderID],[Status] ,[EmployeeID]
,[VendorID] ,[ShipMethodID],[OrderDate]
,[ShipDate] ,[SubTotal] ,[TaxAmt],[Freight]
,[TotalDue]
FROM
[AdventureWorks].[Purchasing].[PurchaseOrderH
eader]
WHERE [TotalDue] > 300000
FOR XML RAW
FOR XML RAW
<row PurchaseOrderID="4007" Status="2" EmployeeID="164"
VendorID="102" ShipMethodID="3" OrderDate="2004-0401T00:00:00" ShipDate="2004-04-26T00:00:00"
SubTotal="554020.0000" TaxAmt="44321.6000"
Freight="11080.4000" TotalDue="609422.0000"/>
<row PurchaseOrderID="4008" Status="2" EmployeeID="244"
VendorID="95" ShipMethodID="3" OrderDate="2004-0523T00:00:00" ShipDate="2004-06-17T00:00:00"
SubTotal="396729.0000" TaxAmt="31738.3200"
Freight="7934.5800" TotalDue="436401.9000"/>
<row PurchaseOrderID="4012" Status="2" EmployeeID="231"
VendorID="29" ShipMethodID="3" OrderDate="2004-0725T00:00:00" ShipDate="2004-08-19T00:00:00"
SubTotal="997680.0000" TaxAmt="79814.4000"
Freight="19953.6000" TotalDue="1097448.0000"/>
FOR XML RAW, ELEMENTS
<row>
<PurchaseOrderID>4007</PurchaseOrderID>
<Status>2</Status>
<EmployeeID>164</EmployeeID>
<VendorID>102</VendorID>
<ShipMethodID>3</ShipMethodID>
<OrderDate>2004-04-01T00:00:00</OrderDate>
<ShipDate>2004-04-26T00:00:00</ShipDate>
<SubTotal>554020.0000</SubTotal>
<TaxAmt>44321.6000</TaxAmt>
<Freight>11080.4000</Freight>
<TotalDue>609422.0000</TotalDue>
</row>
<row><PurchaseOrderID>4008</PurchaseOrderID><Status>2</Status><EmployeeID>244</EmployeeID><Vend
orID>95</VendorID><ShipMethodID>3</ShipMethodID><OrderDate>2004-0523T00:00:00</OrderDate><ShipDate>2004-0617T00:00:00</ShipDate><SubTotal>396729.0000</SubTotal><TaxAmt>31738.3200</TaxAmt><Freight>793
4.5800</Freight><TotalDue>436401.9000</TotalDue></row>
<row><PurchaseOrderID>4012</PurchaseOrderID><Status>2</Status><EmployeeID>231</EmployeeID><Vend
orID>29</VendorID><ShipMethodID>3</ShipMethodID><OrderDate>2004-0725T00:00:00</OrderDate><ShipDate>2004-0819T00:00:00</ShipDate><SubTotal>997680.0000</SubTotal><TaxAmt>79814.4000</TaxAmt><Freight>199
53.6000</Freight><TotalDue>1097448.0000</TotalDue></row>
FOR XML RAW('Order'),
ROOT('Orders'), ELEMENTS
<Orders>
<Order>
<PurchaseOrderID>4007</PurchaseOrderID>
<Status>2</Status>
<EmployeeID>164</EmployeeID>
<VendorID>102</VendorID>
<ShipMethodID>3</ShipMethodID>
<OrderDate>2004-04-01T00:00:00</OrderDate>
<ShipDate>2004-04-26T00:00:00</ShipDate>
<SubTotal>554020.0000</SubTotal>
<TaxAmt>44321.6000</TaxAmt>
<Freight>11080.4000</Freight>
<TotalDue>609422.0000</TotalDue>
</Order>
<Order><PurchaseOrderID>4008</PurchaseOrderID><Status>2</Status><EmployeeID>244</EmployeeID><VendorID>95<
/VendorID><ShipMethodID>3</ShipMethodID><OrderDate>2004-05-23T00:00:00</OrderDate><ShipDate>2004-0617T00:00:00</ShipDate><SubTotal>396729.0000</SubTotal><TaxAmt>31738.3200</TaxAmt><Freight>7934.5800</Freigh
t><TotalDue>436401.9000</TotalDue></Order>
<Order><PurchaseOrderID>4012</PurchaseOrderID><Status>2</Status><EmployeeID>231</EmployeeID><VendorID>29<
/VendorID><ShipMethodID>3</ShipMethodID><OrderDate>2004-07-25T00:00:00</OrderDate><ShipDate>2004-0819T00:00:00</ShipDate><SubTotal>997680.0000</SubTotal><TaxAmt>79814.4000</TaxAmt><Freight>19953.6000</Freig
ht><TotalDue>1097448.0000</TotalDue></Order>
</Orders>
FOR XML RAW(‘Order’), ROOT(‘Orders’),
ELEMENTS XSINIL, XMLSCHEMA
•
•
•
•
•
<Orders xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<xsd:schema targetNamespace="urn:schemas-microsoft-com:sql:SqlRowSet1"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:sqltypes="http://schemas.microsoft.com/sqlserver/2004/sqltypes"
elementFormDefault="qualified">
<xsd:import namespace="http://schemas.microsoft.com/sqlserver/2004/sqltypes"
schemaLocation="http://schemas.microsoft.com/sqlserver/2004/sqltypes/sqltypes.xsd"/
>
<xsd:element name="Order"><xsd:complexType><xsd:sequence><xsd:element
name="PurchaseOrderID" type="sqltypes:int" nillable="1"/><xsd:element
name="Status" type="sqltypes:tinyint" nillable="1"/><xsd:element name="EmployeeID"
type="sqltypes:int" nillable="1"/><xsd:element name="VendorID" type="sqltypes:int"
nillable="1"/><xsd:element name="ShipMethodID" type="sqltypes:int"
nillable="1"/><xsd:element name="OrderDate" type="sqltypes:datetime"
nillable="1"/><xsd:element name="ShipDate" type="sqltypes:datetime"
nillable="1"/><xsd:element name="SubTotal" type="sqltypes:money"
nillable="1"/><xsd:element name="TaxAmt" type="sqltypes:money"
nillable="1"/><xsd:element name="Freight" type="sqltypes:money"
nillable="1"/><xsd:element name="TotalDue" type="sqltypes:money"
nillable="1"/></xsd:sequence></xsd:complexType></xsd:element>
</xsd:schema>
<Order xmlns="urn:schemas-microsoft-com:sql:SqlRowSet1">
<PurchaseOrderID>4007</PurchaseOrderID>
<Status>2</Status><EmployeeID>164</EmployeeID><VendorID>102</VendorID><ShipMethodID>3</ShipM
ethodID><OrderDate>2004-04-01T00:00:00</OrderDate><ShipDate>2004-0426T00:00:00</ShipDate><SubTotal>554020.0000</SubTotal><TaxAmt>44321.6000</TaxAmt><Freight>1
1080.4000</Freight><TotalDue>609422.0000</TotalDue></Order><Order xmlns="urn:schemasmicrosoftcom:sql:SqlRowSet1"><PurchaseOrderID>4008</PurchaseOrderID><Status>2</Status><EmployeeID>24
4</EmployeeID><VendorID>95</VendorID><ShipMethodID>3</ShipMethodID><OrderDate>2004-0523T00:00:00</OrderDate><ShipDate>2004-0617T00:00:00</ShipDate><SubTotal>396729.0000</SubTotal><TaxAmt>31738.3200</TaxAmt><Freight>7
934.5800</Freight><TotalDue>436401.9000</TotalDue></Order>
<Order xmlns="urn:schemas-microsoft-com:sql:SqlRowSet1">
<PurchaseOrderID>4012</PurchaseOrderID><Status>2</Status><EmployeeID>231</EmployeeID><VendorID
>29</VendorID><ShipMethodID>3</ShipMethodID>
<OrderDate>2004-07-25T00:00:00</OrderDate>
<ShipDate>2004-08-19T00:00:00</ShipDate>
<SubTotal>997680.0000</SubTotal>
<TaxAmt>79814.4000</TaxAmt>
<Freight>19953.6000</Freight>
<TotalDue>1097448.0000</TotalDue>
</Order>
</Orders>
Режим AUTO
• When RAW mode is not enough, FOR XML AUTO provides
a few more ways to shape your XML output.
• Its usefulness derives from its capability to produce
nested XML elements from rows derived by joining
multiple tables, in contrast to the flat structure of RAW
mode.
• The ROOT keyword introduced earlier also applies with
AUTO mode, and it is good practice to continue to use it
in your queries.
• Like RAW mode, AUTO mode produces attribute-centric
XML by default, but you can change this by using the
ELEMENTS keyword. XSINIL and XMLSCHEMA are also
applicable here, having the same effect as with RAW
mode.
SELECT
Color, Offer.SpecialOfferId Id, Product.ProductId Id,
Name, Description [Desc], Size
FROM Sales.SpecialOffer Offer
JOIN Sales.SpecialOfferProduct OP ON
OP.SpecialOfferId = Offer.SpecialOfferId
JOIN Production.Product Product ON
Product.ProductId = OP.ProductId
WHERE Name LIKE ‘Mountain Bike%’
FOR XML AUTO, ELEMENTS XSINIL, ROOT(‘MountainBikeSpecials’)
go
Результат:
<MountainBikeSpecials
xmlns:xsi=”http://www.w3.org/200
1/XMLSchema-instance”>
<Product>
<Color>White</Color>
<Id>710</Id>
<Name>Mountain Bike Socks, L
</Name>
<Size>L</Size>
<Offer>
<Id>1</Id>
<Desc>No Discount</Desc>
</Offer>
</Product>
<Product>
<Color>White</Color>
<Id>709</Id>
<Name>Mountain Bike Socks, M</Name>
<Size>M</Size>
<Offer>
<Id>1</Id>
<Desc>No Discount</Desc>
</Offer>
<Offer>
<Id>2</Id>
<Desc>Volume Discount 11 to 14</Desc>
</Offer>
<Offer>
<Id>3</Id>
<Desc>Volume Discount 15 to 24</Desc>
</Offer>
<Offer>
<Id>4</Id>
<Desc>Volume Discount 25 to 40</Desc>
</Offer>
</Product>
</MountainBikeSpecials>
SELECT
PurchaseOrderID, Status,
EmployeeID, VendorID, ShipMethodID,
OrderDate, ShipDate, SubTotal, TaxAmt,
Freight, TotalDue
FROM Purchasing.PurchaseOrderHeader
WHERE (TotalDue > 300000)
FOR XML AUTO
• <Purchasing.PurchaseOrderHeader PurchaseOrderID="4007" Status="2"
EmployeeID="164" VendorID="102" ShipMethodID="3"
OrderDate="2004-04-01T00:00:00" ShipDate="2004-04-26T00:00:00"
SubTotal="554020.0000" TaxAmt="44321.6000" Freight="11080.4000"
TotalDue="609422.0000"/>
• <Purchasing.PurchaseOrderHeader PurchaseOrderID="4008" Status="2"
EmployeeID="244" VendorID="95" ShipMethodID="3"
OrderDate="2004-05-23T00:00:00" ShipDate="2004-06-17T00:00:00"
SubTotal="396729.0000" TaxAmt="31738.3200" Freight="7934.5800"
TotalDue="436401.9000"/>
• <Purchasing.PurchaseOrderHeader PurchaseOrderID="4012" Status="2"
EmployeeID="231" VendorID="29" ShipMethodID="3"
OrderDate="2004-07-25T00:00:00" ShipDate="2004-08-19T00:00:00"
SubTotal="997680.0000" TaxAmt="79814.4000" Freight="19953.6000"
TotalDue="1097448.0000"/>
Режим EXPLICIT
• FOR XML EXPLICIT is a powerful, oft-maligned, somewhat
daunting mode of SQL Server XML production.
• It allows for the shaping of row data in any desirable XML
structure, but the SQL required to produce it can easily end up
being hundreds (or, in some cases, thousands) of lines long,
leading to a potential maintenance headache.
• With EXPLICIT mode, the query author is responsible for
making sure the XML is well formed and that the rowset
generated behind the scenes corresponds to a very particular
format.
• The FOR XML PATH statement renders FOR XML EXPLICIT
obsolete except when you need to output column values as
CDATA.
• This section therefore briefly covers the required query
structure for and provides an example of this particular case.
Режим PATH
•
PATH mode is the latest and best addition to the FOR XML syntax. It provides a
straightforward way of using a limited XPath syntax to specify the shaping of queryproduced XML.
• It is also a very compact syntax in comparison with some of the other modes, especially
EXPLICIT.
• Let’s look at how PATH mode works by re-creating the XML produced in Listing 47.9,
this time using PATH mode. Listing 47.10 illustrates this mode.
SELECT
Reason.ScrapReasonId,
Name ‘text()’,
WorkOrderId ‘WorkOrder/@WorkOrderId’,
ScrappedQty ‘WorkOrder/@ScrappedQuantity’
FROM Production.ScrapReason Reason
JOIN Production.WorkOrder WorkOrder
ON Reason.ScrapReasonId = WorkOrder.ScrapReasonID
WHERE Reason.ScrapReasonId = 12
FOR XML PATH(‘ScrapReason’), ROOT(‘ScrappedWorkOrders’)
go
<ScrappedWorkOrders>
<ScrapReason>
<ScrapReasonId>12</ScrapReasonId>
Thermoform temperature too high
<WorkOrder WorkOrderId=”2573” ScrappedQuantity=”14” />
</ScrapReason>
<ScrapReason>
<ScrapReasonId>12</ScrapReasonId>
Thermoform temperature too high
<WorkOrder WorkOrderId=”4972” ScrappedQuantity=”1” />
</ScrapReason>
<ScrapReason>
<ScrapReasonId>12</ScrapReasonId>
Thermoform temperature too high
<WorkOrder WorkOrderId=”7771” ScrappedQuantity=”6” />
</ScrapReason>
<ScrapReason>
<ScrapReasonId>12</ScrapReasonId>
Thermoform temperature too high
<WorkOrder WorkOrderId=”9071” ScrappedQuantity=”1” />
</ScrapReason>
{...}
</ScrappedWorkOrders>
SELECT [PurchaseOrderID],[Status],
[EmployeeID],[VendorID] ,[ShipMethodID],
[OrderDate],[ShipDate],[SubTotal],[TaxAmt],
[Freight],[TotalDue]
FROM
[AdventureWorks].[Purchasing].[PurchaseOrd
erHeader]
WHERE [TotalDue] > 300000
SELECT [PurchaseOrderHeader].[PurchaseOrderID]
,[PurchaseOrderHeader].[Status],[PurchaseOrderHeader].[EmployeeID]
,[PurchaseOrderHeader].[VendorID],[PurchaseOrderHeader].[ShipMethodID]
,[PurchaseOrderHeader].[OrderDate],[PurchaseOrderHeader].[ShipDate]
,[PurchaseOrderHeader].[SubTotal],[PurchaseOrderHeader].[TaxAmt]
,[PurchaseOrderHeader].[Freight],[PurchaseOrderHeader].[TotalDue]
,[PurchaseOrderDetail].[OrderQty],[PurchaseOrderDetail].[ProductID]
,[PurchaseOrderDetail].[UnitPrice]
FROM [Purchasing].[PurchaseOrderHeader] PurchaseOrderHeader
INNER JOIN Purchasing.PurchaseOrderDetail PurchaseOrderDetail
ON PurchaseOrderHeader.[PurchaseOrderID] =
PurchaseOrderDetail.[PurchaseOrderID]
WHERE [PurchaseOrderHeader].[TotalDue] > 300000
Функция OPENXML()
Функции SQL Server для доступа и
работы с внешними данными
• OPENQUERY() – выполняет запрос к внешнему
серверу и возвращает список записей;
• OPENROWSET () – аналогично OPENQUERY(), а
также для массовой загрузки данных из
файлов;
• OPENXML () – предоставляет набор записей их
XML документа.
Функция OPENXML()
• Функция OPENXML позволяет просматривать XML документ в виде набора
записей (rowset view).
• OPENXML может использоваться в SQL операторах , в которых могут
использоваться таблицы, представления (view) или функция OPENROWSET.
• Обычный вызов функции OPENXML() включает
– вызов системной хранимой процедуры для подготовки указателя (handle) на
XML документ;
– вызов функции OPENXML() для получения результирующего набора;
– вызов системной хранимой процедуры для освобождения полученного на
данный документ указателя.
• В связи с такими специфическими требованиями до и после вызова
OPENXML() нужно вызывать системную хранимую процедуру.
• Функция OPENXML() не может быть вызвана из другой функции или
использована в операциях с множествами (set-based operation).
– Например, to read information from an XML formatted string stored in a SQL Server
column, a WHILE loop is required, because OPENXML() can process only one XML
document at a time.
– Before and after processing each document, calls to system stored procedures to
initialize and release the document handle are necessary.
Выполнение грамматического разбора
и запросов к XML документам
•
Почти для всех приложений, выполняющих обмен информацией в XML формате
требуется модуль или компонент, способный извлекать информацию из XML
разметки.
– Например, для desktop приложения, читающего RSS может потребоваться извлечение
информации о каналах (channel) и элементах (item) из XML документа, прежде чем он будет
показан в пользовательском интерфейсе (UI element).
– Клиентскому приложению, вызывающему Web Service с прогнозом погоды или о биржевых
ценах требуется выполнить разбор полученного XML документа и извлечь требуемые
элементы информации.
•
Многие из этих приложений хранят информацию, полученную из одной или
нескольких реляционных таблиц.
– Примером является Web Service, получающий от потребителей информацию о заказах на
покупки. Web Service может отправлять информацию заказа хранимой процедуре, для
сохранения данной информации в наборе реляционных таблиц.
•
•
SQL Server имеет мощную функцию обработки XML - OPENXML(), которая
способна разделить XML документ в результирующий набор. Приложения могут
передать весь XML документ хранимой процедуре SQL Server, а не заниматься
самим грамматическим разбором XML документа.
Приложения, которые используют несколько параметров (например, заказы на
продажи и покупки) могут использовать такие возможности сервера по обработке
XML и отправлять всю информацию в виде единого XML документа с помощью
одного вызова хранимой процедуры.
Пример использования
функции OPENXML
•
В следующем примере показано применение процедуры OPENXML в
инструкции INSERT и инструкции SELECT.
– Образец XML-документа содержит элементы <Customers> и <Orders>.
•
•
•
•
Сначала вызывается хранимая процедура sp_xml_preparedocument для проведения
синтаксического анализа XML-документа. В процессе синтаксического анализа
создается древовидное представление узлов (элементов, атрибутов, текста и
комментариев), входящих в XML-документ.
Затем OPENXML ссылается на этот проанализированный XML-документ и
формирует представление наборов строк для всех частей XML-документа.
Инструкция INSERT, использующая функцию OPENXML, может вставлять данные из
такого набора строк в таблицу базы данных.
Можно вызывать функцию OPENXML несколько раз, получая и обрабатывая
представление в виде набора строк различных частей XML-документа.
– Например, их можно вставить в различные таблицы. Данный процесс также называют
разделение XML-данных по таблицам.
•
Последним шагом обработки является повторный вызов
процедуры sp_xml_removedocument. Это позволяет освободить память,
выделенную для внутреннего древовидного представления XML, создаваемого в
фазе синтаксического анализа.
Пример использования функции OPENXML
•
•
В следующем примере XML-документ разделяется таким образом, что
элементы <Customers> сохраняются в таблице Customers, а
элементы <Orders> сохраняются в таблице Orders с помощью двух
инструкций INSERT.
Этот пример также демонстрирует инструкцию SELECT, использующую
функцию OPENXML, которая получает элементы CustomerID и OrderDate из XMLдокумента.
-- Create tables for later population using OPENXML.
CREATE TABLE Customers (CustomerID varchar(20) primary key, ContactName
varchar(20), CompanyName varchar(20))
GO
CREATE TABLE Orders( CustomerID varchar(20), OrderDate datetime)
GO
DECLARE @docHandle int
DECLARE @xmlDocument nvarchar(max) -- or xml type
SET @xmlDocument = N'<ROOT> <Customers CustomerID="XYZAA" ContactName="Joe"
CompanyName="Company1"> <Orders CustomerID="XYZAA" OrderDate="2000-0825T00:00:00"/> <Orders CustomerID="XYZAA" OrderDate="2000-10-03T00:00:00"/>
</Customers> <Customers CustomerID="XYZBB" ContactName="Steve"
CompanyName="Company2">No Orders yet! </Customers> </ROOT>'
EXEC sp_xml_preparedocument @docHandle OUTPUT, @xmlDocument
-- Use OPENXML to provide rowset consisting of customer data.
INSERT Customers
SELECT * FROM OPENXML(@docHandle, N'/ROOT/Customers') WITH
Customers
-- Use OPENXML to provide rowset consisting of order data.
INSERT Orders
SELECT * FROM OPENXML(@docHandle, N'//Orders') WITH Orders
-- Using OPENXML in a SELECT statement.
SELECT *
FROM OPENXML(@docHandle, N'/ROOT/Customers/Orders')
WITH (CustomerID nchar(5) '../@CustomerID', OrderDate datetime)
-- Remove the internal representation of the XML document.
EXEC sp_xml_removedocument @docHandle
• На рисунке показано XML-дерево, полученное в результате
анализа предыдущего XML-документа и созданное с помощью
хранимой процедуры sp_xml_preparedocument.
XML как реляционные данные:
использование OPENXML
• Функция OPENXML выполняет операцию
обратную FOR XML.
• Функция OPENXML используется в T-SQL
запросах для чтения XML данных и их
декомпозиции в реляционные
результирующие наборы данных.
• OPENXML является частью оператора SELECT
и может использоваться для создания
таблицы их XML документа.
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
DECLARE @XmlDoc XML, @iXml int
SET @XmlDoc = ‘
<ex:ExampleDoc xmlns:ex=”urn:www-samspublishing-com:examples”>
<ex:foo>hello</ex:foo>
<ex:bar>sql!</ex:bar>
</ex:ExampleDoc>’
EXEC sp_xml_preparedocument
@iXml OUTPUT,
@XmlDoc,
‘<ExampleDoc xmlns:ex=”urn:www-samspublishing-com:examples”/>’
SELECT id, parentid, nodetype, localname, prefix
FROM OPENXML(@iXml, ‘/ex:ExampleDoc/ex:foo’)
--WITH (foo varchar(10) ‘/ex:ExampleDoc/ex:foo’)
EXEC sp_xml_removedocument @iXml
go
id
parentid nodetype localname prefix
------ ------------ ------------- ------------- ----3
0
1
foo
ex
5
3
3
#text
NULL
Встроенный XML тип данных
Тип данных XML
•
•
•
Наиболее существенным дополнением возможностей SQL Server работать с
XML данными было введение специально типа данных XML.
Тип данных XML может хранить полные XML документы или их части.
Тип данных XML может использоваться аналогично тому, как используются и
другие типы данных SQL Server:
– можно создавать таблицы с XML колонками,
– можно объявлять XML переменные и использовать их в качестве параметров и
возвращаемых значений.
•
•
•
•
С помощью XML типа данных в SQL Servere реализовано ограниченное
подмножество языка XQuery и запросы на языке T-SQL могут использовать язык
XQuery для получения информации из XML колонок и переменных.
Поддержка языка XQuery встроена в Relational Engine сервера SQL Server и
оптимизатор запросов Query Optimizer может создавать планы выполнения
запросов, которые содержат операции реляционных запросов и операции
XQuery.
Результаты XQuery операций могут связываться с (joined) реляционными
данными, а реляционные данные могут связываться с результатами XQuery
операций.
SQL Server поддерживает создание специальных типов индексов для XML
колонок для оптимизации XQuery операций.
Работа с XML в СУБД SQL Server
• Новый тип данных «xml».
Сведения о XML-столбце
Store.Demographics
• Пример базы данных Adventure Works: оптовые посредники покупают
продукты в компании Adventure Works Cycles и продают их розничным
торговцам.
• Обычные демографические данные об этих оптовых посредниках (годовой
доход, ежегодные продажи, вид бизнеса и год начала деятельности)
хранятся в столбце Demographics типа xml в таблице Store.
• Это типизированный xml-столбец. Для этого столбца используется XMLсхема AdventureWorks StoreSurvey.
• Пример экземпляра XML, хранящегося в столбце Store.Demographics.
<StoreSurvey xmlns="http://schemas.microsoft.com/sqlserver/2004/07/adventureworks/StoreSurvey">
<AnnualSales>300000</AnnualSales> <AnnualRevenue>30000</AnnualRevenue>
<BankName>International Bank</BankName>
<BusinessType>BM</BusinessType> <YearOpened>1970</YearOpened>
<Specialty>Road</Specialty> <SquareFeet>7000</SquareFeet>
<Brands>3</Brands> <Internet>T1</Internet>
<NumberEmployees>2</NumberEmployees>
</StoreSurvey>
Пример XML колонки в таблице ProductModel
•
Содержание поля Instruction в записи таблицы ProductModel
<root xmlns="http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelManuInstructions">
Adventure Works CyclesFR-210B Instructions for Manufacturing HL Touring Frame. Summary: This document contains
manufacturing instructions for manufacturing the HL Touring Frame, Product Model 7. Instructions are work center
specific and are identified by Work Center ID. These instructions must be followed in the order presented. Deviation from
the instructions is not permitted unless an authorized Change Order detailing the deviation is provided by the Engineering
Manager.
<Location LaborHours="2.5" LotSize="100" MachineHours="3" SetupHours="0.5" LocationID="10">
Work Center 10 - Frame Forming. The following instructions pertain to Work Center 10. (Setup hours = .5, Labor
Hours = 2.5, Machine Hours = 3, Lot Sizing = 100)
<step> Insert <material>aluminum sheet MS-2341</material> into the <tool>T-85A framing tool</tool>. </step>
<step> Attach <tool>Trim Jig TJ-26</tool> to the upper and lower right corners of the aluminum sheet. </step>
<step> Using a <tool>router with a carbide tip 15</tool>, route the aluminum sheet following the jig carefully. </step>
<step> Insert the frame into <tool>Forming Tool FT-15</tool> and press Start. </step>
<step> When finished, inspect the forms for defects per Inspection Specification <specs>INFS-111</specs>. </step>
<step>Remove the frames from the tool and place them in the Completed or Rejected bin as appropriate.</step>
</Location>
<Location LaborHours="1.75" LotSize="1" MachineHours="2" SetupHours="0.15" LocationID="20">
Work Center 20 - Frame Welding. The following instructions pertain to Work Center 20. (Setup hours = .15, Labor
Hours = 1.75, Machine Hours = 2, Lot Sizing = 1)
<step> Assemble all frame components following blueprint <blueprint>1299</blueprint>. </step>
<step> Weld all frame components together as shown in illustration <diag>3</diag></step>
<step> Inspect all weld joints per Adventure Works Cycles Inspection Specification <specs>INFS-208</specs>. </step>
</Location>
…..
</root>
Типизированные и
не типизированные XML данные
•
•
•
•
•
•
Тип данных XML поддерживает XSD с помощью коллекций XML схем, котораяможет
быть создана из определения XML схемы.
XML колонки и переменные могут быть связаны с коллекцией XML схем. XML
колонки и переменные, которые связаны с коллекцией XML схем называются
типизированными XML.
Операции назначения или изменения типизированного XML будут выполнены
успешно только в том случае, если новые значения пройдут проверку на
валидность (validations) определенную в коллекции XML схем.
Типизированные XML имеют много преимуществ по сравнению с
нетипизированными XML колонками и переменными. The most important benefit is
that the validation constraints are always respected. The content of a typed XML
document is always valid as per the schema with which it is associated.
Cпри работе с типизированными XML, SQL Server имеет больше знаний о XML
документе (структуре, типах данных и т.п.) и может генерировать более
оптимизированные планы запросов. Because SQL Server has complete knowledge of
the data types of elements and attributes, storage of typed XML can be made
significantly more compact than untyped XML.
Static type checking is possible with typed XML documents, and SQL Server can detect,
at compile time, if an XQuery expression on a typed XML document is mistyped. Stored
procedures or functions that accept typed XML parameters are protected from receiving
invalid XML documents, as SQL Server will perform implicit validation of the XML value
against the schema collection before accepting the parameter value.
Создание и использование XML
колонок
• XML тип данных в большинстве случаев может использоваться
аналогично тому, как используются другие типы данных SQL
сервера (целые, вещественные и т.п.).
• Однако имеются некоторые исключения.
– Например, XML колонка не может быть добавлена к обычному индексу
или использована в операции сравнения.
• Можно создать таблицу с одной или несколькими XML колонками.
• XML колонки могут быть добавлены к существующей таблице.
• Колонки с типами данных
VARCHAR/NVARCHAR/VARBINARY/TEXT/NTEXT могут быть
преобразованы в колонки XML типа данных, если все существующие
значения являются правильными (well-formed) XML значениями
(XML документами, участками XML формата).
• Цельные XML документы могут быть получены с помощью SELECT
запроса, или из XML документов может быть извлечена некоторая
информация
Создание и использование XML
колонок
• XML тип данных в большинстве случаев может использоваться
аналогично тому, как используются другие типы данных SQL
сервера (целые, вещественные и т.п.).
• Однако имеются некоторые исключения.
– Например, XML колонка не может быть добавлена к обычному индексу
или использована в операции сравнения.
• Можно создать таблицу с одной или несколькими XML колонками.
• XML колонки могут быть добавлены к существующей таблице.
• Колонки с типами данных
VARCHAR/NVARCHAR/VARBINARY/TEXT/NTEXT могут быть
преобразованы в колонки XML типа данных, если все существующие
значения являются правильными (well-formed) XML значениями
(XML документами, участками XML формата).
• Цельные XML документы могут быть получены с помощью SELECT
запроса, или из XML документов может быть извлечена некоторая
информация
Создание коллекции XML схем
CREATE XML SCHEMA COLLECTION
Sales.FeedbackSchemaCollection AS
‘<?xml version=”1.0”?>
<xsd:schema
xmlns:xsd=”http://www.w3.org/2001/XMLSchema”
targetNamespace=”urn:www-samspublishingcom:examples:feedback_review_xsd”
xmlns=”urn:www-samspublishingcom:examples:feedback_review_xsd”
elementFormDefault=”qualified”
attributeFormDefault=”unqualified”>
<xsd:element name=”feedback_review”
type=”feedbackReviewType”/>
<xsd:complexType name=”feedbackReviewType”>
<xsd:sequence minOccurs=”1”
maxOccurs=”unbounded”>
<xsd:element name=”order” type=”orderType”/>
</xsd:sequence>
<xsd:attribute
name=”product_id”
type=”xsd:integer”
use=”optional”/>
</xsd:complexType>
<xsd:complexType name=”feedbackType” mixed=”true”>
<xsd:attribute name=”id” type=”xsd:integer”
use=”required”/>
</xsd:complexType>
<xsd:complexType name=”orderType”>
<xsd:choice minOccurs=”0” maxOccurs=”unbounded”>
<xsd:element name=”customer_comment”
type=”feedbackType”/>
<xsd:element name=”company_response”
type=”feedbackType”/>
</xsd:choice>
<xsd:attribute name=”id” type=”xsd:integer”
use=”required”/>
<xsd:attribute name=”type” use=”required”>
<xsd:simpleType>
<xsd:restriction base=”xsd:string”>
<xsd:enumeration value=”parts”/>
<xsd:enumeration value=”product”/>
<xsd:enumeration value=”service”/>
</xsd:restriction>
</xsd:simpleType>
1896 CHAPTER 47 Using XML in SQL Server 2008
</xsd:attribute>
</xsd:complexType>
</xsd:schema>’
Создаем таблицу использующую
колонку со схемой
CREATE TABLE Sales.FeedbackReview
(
FeedbackReviewId int IDENTITY(1, 1) NOT NULL PRIMARY KEY,
ProductId int NULL REFERENCES Production.Product,
FeedbackReviewXml xml (DOCUMENT Sales.FeedbackSchemaCollection) NOT
NULL,
CONSTRAINT ProductIdMatches
CHECK (Sales.fnCheckProductId(FeedbackReviewXml) = ProductId)
)
CREATE FUNCTION Sales.fnCheckProductId (@FeedbackReviewXml xml)
RETURNS int
AS
BEGIN
DECLARE @ProductId int
SELECT @ProductId = @FeedbackReviewXml.value
(‘declare namespace
fr=”urn:www-samspublishing-com:examples:feedback_review_xsd”;
/fr:feedback_review[1]/@product_id’, ‘int’)
RETURN @ProductId
END
Вставка записи в таблицу
INSERT Sales.FeedbackReview
SELECT
NULL,
‘<feedback_review
xmlns=”urn:www-samspublishing-com:examples:feedback_review_xsd”>
<order id=”353” type=”service”>
<customer_comment id=”131”>
You guys said you'd be here on Monday.
</customer_comment>
<company_response id=”242”>I said Wednesday!</company_response>
</order>
</feedback_review>’
Загрузка XML из файлов
• Данный пример показывает, как вставить строку в
таблицу T.
• Значения XML колонки загружаются из файла
C:\MyFile\xmlfile.xml в виде CLOB, а для колонки
целого типа задается значение 10.
INSERT INTO T
SELECT 10, xCol
FROM (SELECT *
FROM OPENROWSET (BULK
'C:\MyFile\xmlfile.xml', SINGLE_CLOB) AS xCol)
AS R(xCol)
Выполнение проверки XML
документов
•
•
•
•
•
•
Одним из требований любого серьезного приложения является набор процессов
проверки правильности структуры используемой информации.
Правильно составленная программа должна полностью проверять все входные
параметры перед выполнением их реальной обработки.
Обычно полная проверка параметров защищает приложение и БД от логических
ошибок и ошибок в данных. Она помогает защитить данные от злоумышленных
действий (например, таких, как введение SQL (SQL injection)).
При обмене данными в XML формате требуется их более строгая проверка, так
как возможности задания неправильных значений увеличиваются.
Приложение передающее значение ‘‘тридцать’’ для параметра хранимой
процедуры @age (@age INT) получит сообщение об ошибке преобразования,
сразу же после того, как SQL Server попытается выполнить неявную проверку типа
данных.
Разработчик составляющий хранимую процедуру не должен выполнять проверки,
гарантирующие, что все параметры целого типа являются правильными целыми
значениями. Данный разработчик должен только выполнять проверки
специфичные для бизнес-логики, как например проверку предельных значений
возраста сотрудников, чтобы гарантировать, что он попадает в приемлемый
интервал (например, от 18 до 65).
•
•
•
Выполнение проверки XML
документов (2)
При использовании XML параметров SQL Server не сможет обнаружить такую
возможную ошибку в XML документе, как
‘‘<Employee age=˝кто его знает˝/>’’
так как атрибут @age не связан с конкретным типом данных и SQL Server не знает,
как его проверить.
Это указывает на то, что для XML документов требуется намного более сложная
проверка, чем для не-XML параметров.
Например:
– часто требуется чтобы элементы XML документа следовали в заданном порядке. An
application that parses the XML document sequentially might require that the OrderDate element
should precede the ExpectedShippingDate element to validate the shipping date based on the
order date.
– Structure of the XML should be validated. For example, an application might expect the employee
address under the employee element, and the zip code as an attribute of the address element.
– Certain elements may be optional and certain elements mandatory.
– Certain elements may appear more than once and others may be allowed only once.
– Data type validations may be needed. For example, age should be an integer value.
– Restrictions might be needed on the accepted range of values, such as age of an employee should
be between 18 and 65.
– Certain values may follow specific formats. For example, an application might require phone
numbers to be in the format of (999) 999-9999, or social security numbers must be 999-99-9999.
Встроенные методы для
работы с XML типом данных
Встроенные методы для типа
данных xml
• SQL Server предоставляет 5 встроенных методов для типа данных xml:
1) query() – выполнение выражения на языке XQuery, преобразующее
значение поля в список узлов, который может быть переформатирован
нужным способом. Результатом является не типизированный XML.
2) exists() – выполнение проверки того, является ли результат выполнения
XQuery запроса пустым (нет искомых узлов). Результат 1 (узлы есть) или 0
(узлов нет),
3) value() – извлечение одного (т.е. скалярного) значения из XML и
преобразование его реляционный тип данных SQL Server (например, int,
varchar),
4) nodes() – используется XQuery выражение для разделения XML данных в
набор записей (rowset); аналогично работе OPENXML.
5) modify() – изменение содержания XML данных с помощью функций
XQuery: insert, replace, delete.
• Для вызова этих методов их нужно указать через точку после имени
колонки с типом данных xml:
ColumnName.MethodName([MethodParameters]) syntax.
Метод query()
Использование языка XQuery в SQL
Server
• К значениям типа данных xml можно выполнять
запросы, описанные на языке XQuery.
• XQuery выражения встроены в язык Transact-SQL.
Transact-SQL это версия языка SQL, используемая в
SQL Server.
• Microsoft has learned from its past mistakes and has
chosen to separate the nonstandard update
functionality from the standardized XQuery.
• This way, it can add the capability to insert, delete, and
replace, when these become part of XQuery, without
breaking past code.
• It will then deprecate the nonstandard extensions and
eventually phase them out.
Расширение языка XQuery в SQL
Server
• Стандарт XQuery W3C ограничен тем, что он может выполнять
запросы только к XML источникам данныхdata source.
• В XQuery 1.0 нет возможностей удалять, вставлять или менять
данные.
• В SQL Server 2005, the XML Data Modification Language (DML)
adds three keywords to the functionality available in XQuery 1.0:
– delete
– Insert
– replace value of
• Note that although SQL itself is not case sensitive, the preceding
commands are; if you use DELETE instead of delete, you will receive
a cryptic error message.
• XQuery немного походит на SQL, тем что для поиска
требуемых узлов использует семантику аналогичную
SELECT-FROM-WHERE-ORDER BY.
• It also bears a resemblance to writing foreach loops with
object iterators in a language such as C#.
• It is unique in that it combines the navigational power of
XPath to locate nodes and (in the same expressions) allows
for new XML generation on the fly, all in one tight syntax
package built especially for processing XML.
• To use XQuery effectively, you need to have at least a
rudimentary understanding of XPath. A great starting point
is the World Wide Web Consortium’s (W3C’s) site, at
www.w3.org/TR/xpath20/.
Использование XPath выражений
• XPath is used for locating XML elements and attributes within an XML
document and navigating through the XML tree. Every element and
attribute within an XML document has a unique ‘‘path.’’ For example:
’<Items>
<ItemNumber>1003</ItemNumber>
<ItemNumber>1004</ItemNumber>
</Items>’
•
• In the preceding example, the path to the first ItemNumber element is
/Items/ItemNumber[1] and
• the second is /Items/ItemNumber[2].
• Each element and attribute within an XML document can be uniquely
identified and processed using an XPath expression.
• All the XML data type methods accept XPath expressions to specify the
target element or attribute on which the given operation needs to be
performed.
Selecting XML by Using query()
• The job of query() is to retrieve XML nodes by using XQuery
expressions.
• The result of query() is an instance of untyped xml.
• It takes a single parameter, a string literal containing the
XQuery code itself.
• The parameter to query() cannot be a variable; it must be a
string literal.
• This puts something of a hold on dynamic XQuery
expressions.
• However, declared T-SQL variables and column values are
available for use in XQuery, using the functions
sql:variable() and sql:column() (described later in this
chapter).
•
Each XQuery query is broken into two distinct parts, separated by a semicolon.
– The first part is known as the prolog. This is the place where any namespaces used in the Xpath
expressions and selected nodes are declared.
– The second part is known as the body, and this is the place where XPath and XQuery expressions are
evaluated.
•
The following example declares the act namespace in its query prolog and then selects
any act:eMail nodes from Person.Person.AdditionalContactInfo in its body:
SELECT
AdditionalContactInfo.query(
‘
declare namespace
act=”http://schemas.microsoft.com/sqlserver/2004/07/adventureworks/ContactTypes”;
//act:eMail
‘
)
FROM Person.Person
WHERE ContactId = 2
WITH XMLNAMESPACES
(
‘http://schemas.microsoft.com/sqlserver/2004/07/adventureworks/ContactTypes’
as act
)
SELECT
FirstName,
LastName,
AdditionalContactInfo.query( ‘ //act:eMail ‘)
FROM Person.Contact
WHERE ContactID = 2
FOR XML RAW(‘ContactInfo’), ROOT(‘Contact’)
Результат
<Contact
xmlns:act=”http://schemas.microsoft.com/sqlserver/2004/07/adventurew
orks/
ContactTypes”>
<ContactInfo FirstName=”Catherine” LastName=”Abel”>
<act:eMail xmlns:act=”http://schemas.microsoft.com/sqlserver/2004/07/
adventure-works/ContactTypes”>
<act:eMailAddress>Joe@xyz.com</act:eMailAddress>
<act:SpecialInstructions>
Dont send emails for urgent issues. Use telephone instead.
</act:SpecialInstructions>
</act:eMail>
</ContactInfo>
</Contact>
<Contact xmlns:act="http://schemas.microsoft.com/sqlserver/2004/07/adventureworks/ContactTypes">
<ContactInfo FirstName="Catherine" LastName="Abel">
<act:eMail
xmlns:act="http://schemas.microsoft.com/sqlserver/2004/07/adventureworks/ContactTypes">
<act:eMailAddress>Joe@sample.com</act:eMailAddress>
<act:SpecialInstructions>Do not send e-mail for urgent issues. Use
telephone instead.
</act:SpecialInstructions>
</act:eMail>
</ContactInfo>
</Contact>
SELECT Instructions.query
(
'declare default element namespace
"http://schemas.microsoft.com/sqlserver/2004/07/adventureworks/ProductModelManuInstructions";
for $ContextNode in //Location
return
<LotSize>
{$ContextNode/@LotSize}
</LotSize>‘
) AS Result
FROM
Production.ProductModel
WHERE
(ProductModelID = 10)
• Результат
<Number>1</Number>
<Number>2</Number>
<Number>3</Number>
• Вместо XPath выражения можно использовать
связанную переменную для выполнения итераций по
множеству значений, а не узлов, as in the following
example:
SELECT Instructions.query(‘
for $ContextNode in (1, 2, 3)
return
<Number>
{$ContextNode }
</Number>
‘) as Result
FROM Production.ProductModel
WHERE ProductModelID = 10
Содержание поля Instruction в таблице
ProductModel
<root xmlns="http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelManuInstructions">
Adventure Works CyclesFR-210B Instructions for Manufacturing HL Touring Frame. Summary: This document contains
manufacturing instructions for manufacturing the HL Touring Frame, Product Model 7. Instructions are work center
specific and are identified by Work Center ID. These instructions must be followed in the order presented. Deviation from
the instructions is not permitted unless an authorized Change Order detailing the deviation is provided by the Engineering
Manager.
<Location LaborHours="2.5" LotSize="100" MachineHours="3" SetupHours="0.5" LocationID="10">
Work Center 10 - Frame Forming. The following instructions pertain to Work Center 10. (Setup hours = .5, Labor
Hours = 2.5, Machine Hours = 3, Lot Sizing = 100)
<step> Insert <material>aluminum sheet MS-2341</material> into the <tool>T-85A framing tool</tool>. </step>
<step> Attach <tool>Trim Jig TJ-26</tool> to the upper and lower right corners of the aluminum sheet. </step>
<step> Using a <tool>router with a carbide tip 15</tool>, route the aluminum sheet following the jig carefully. </step>
<step> Insert the frame into <tool>Forming Tool FT-15</tool> and press Start. </step>
<step> When finished, inspect the forms for defects per Inspection Specification <specs>INFS-111</specs>. </step>
<step>Remove the frames from the tool and place them in the Completed or Rejected bin as appropriate.</step>
</Location>
<Location LaborHours="1.75" LotSize="1" MachineHours="2" SetupHours="0.15" LocationID="20">
Work Center 20 - Frame Welding. The following instructions pertain to Work Center 20. (Setup hours = .15, Labor
Hours = 1.75, Machine Hours = 2, Lot Sizing = 1)
<step> Assemble all frame components following blueprint <blueprint>1299</blueprint>. </step>
<step> Weld all frame components together as shown in illustration <diag>3</diag></step>
<step> Inspect all weld joints per Adventure Works Cycles Inspection Specification <specs>INFS-208</specs>. </step>
</Location>
…..
</root>
<LotSize xmlns="http://schemas.microsoft.com/sqlserver/2004/07/adventureworks/ProductModelManuInstructions" LotSize="100" />
<LotSize xmlns="http://schemas.microsoft.com/sqlserver/2004/07/adventureworks/ProductModelManuInstructions" LotSize="1" />
<LotSize xmlns="http://schemas.microsoft.com/sqlserver/2004/07/adventureworks/ProductModelManuInstructions" LotSize="1" />
<LotSize xmlns="http://schemas.microsoft.com/sqlserver/2004/07/adventureworks/ProductModelManuInstructions" LotSize="20" />
<LotSize xmlns="http://schemas.microsoft.com/sqlserver/2004/07/adventureworks/ProductModelManuInstructions" LotSize="1" />
<LotSize xmlns="http://schemas.microsoft.com/sqlserver/2004/07/adventureworks/ProductModelManuInstructions" LotSize="1" />
Пример запроса
SELECT
Resume.query('declare namespace
ns="http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/Resume";
<Achievements>
{
for $EducationNode in //ns:Education
order by xs:date(string($EducationNode/ns:Edu.EndDate[1])) descending
return
<Degree>
<DateAwarded>
{ string($EducationNode/ns:Edu.EndDate[1]) }
</DateAwarded>
<Name>
{ string($EducationNode/ns:Edu.Degree[1]) }
</Name>
</Degree>
}
</Achievements>
') AS Expr1
FROM
HumanResources.JobCandidate
WHERE
(JobCandidateID = 2)
Результат
<Achievements>
<Degree>
<DateAwarded>
1997-06-03Z
</DateAwarded>
<Name>
Bachelor of Science
</Name>
</Degree>
<Degree>
<DateAwarded>
1993-06-12Z
</DateAwarded>
<Name>
Diploma
</Name>
</Degree>
</Achievements>
Работа с таблицу, имеющей XML
колонку
•
Создание таблицы с XML колонкой:
DECLARE @t TABLE (OrderID INT, OrderData XML )
•
Вставка новой строки в таблицу с XML колонкой
INSERT INTO @t(OrderID, OrderData)
SELECT 1,
‘<CustomerNumber>1001</CustomerNumber>
<Items>
<Item ItemNumber="1001" Quantity="1" Price="950"/>
<Item ItemNumber="1002" Quantity="1" Price="650" />
</Items>’
•
Пример SELECT запроса, извлекающего из таблицы колонку обычного типа (INT) и значение из XML
документа, хранящегося в каждой записи (row):
SELECT
OrderID,
OrderData.value(’CustomerNumber[1]’ , ’CHAR(4)’) AS CustomerNumber
FROM @t
•
Полученный результат выборки
OrderID
CustomerNumber
-----------------------1
1001
Более сложный запрос к XML
колонке
•
•
•
•
Код запроса станет более сложным, если требуется извлечь более чем один элемент из XML
документов, хранящихся в колонке таблицы. Такой запрос должен формировать более чем одну
запись (row) для каждой записи (row) хранимой в таблице.
Для этого может быть использован метод nodes() типа данных XML, чтобы получить доступ к
каждому элементу XML документа.
Коллекция XML элементов, возвращаемая методом nodes() может быть объединена с базовой
таблицей с помощью оператора CROSS APPLY, как показано в следующем примере:
SELECT
OrderID,
o.value(’@ItemNumber’, ’CHAR(4)’) AS ItemNumber,
o.value(’@Quantity’, ’INT’) AS Quantity,
o.value(’@Price’, ’MONEY’) AS Price
FROM @t
CROSS APPLY OrderData.nodes(’/Items/Item’) x(o)
Результат выполнения запроса
OrderID
----------1
1
ItemNumber
---------1001
1002
Quantity
----------1
1
Price
----------950.00
650.00
Объявление и использование XML
переменных
• Just like other SQL Server native data types, XML variables can be
created and used in T-SQL batches, stored procedures, functions,
and so on. The following example demonstrates a few different
ways an XML variable can be declared:
-- Объявление не типизированной XML переменной
DECLARE @x XML
-- Declare a TYPED XML Variable
DECLARE @x XML(CustomerSchema)
-- Declare a TYPED XML DOCUMENT Variable
DECLARE @x XML(DOCUMENT CustomerSchema)
-- Declare a TYPED XML CONTENT variable
DECLARE @x XML(CONTENT CustomerSchema)
Использование XML переменной в
запросе
•
•
•
•
•
•
•
•
Имеется небольшое различие в записи XQuery выражения для XML переменной и XML колонки.
При работе с XML variable, the query will always process only one document at a time. However, while
working with an XML column, more than one XML document may be processed in a single batch
operation. Because of this, the CROSS APPLY operator is required while running such a query on an XML
column (as demonstrated in the previous example).
Пример использования в запросе XML переменной :
DECLARE @x XML
SELECT @x = ‘
<CustomerNumber>1001</CustomerNumber>
<Items>
<Item ItemNumber="1001" Quantity="1" Price="950"/>
<Item ItemNumber="1002" Quantity="1" Price="650" />
</Items>’
SELECT
o.value(’@ItemNumber’,’CHAR(4)’) AS ItemNumber,
o.value(’@Quantity’,’INT’) AS Quantity,
o.value(’@Price’,’MONEY’) AS Price
FROM @x.nodes(’/Items/Item’) x(o)
Полученный результат
ItemNumber
Quantity Price
---------------------------------------1001
1
950.00
1002
1
650.00
Загрузка и запросы к XML документам,
расположенным в файлах
•
•
•
•
•
The capability to load XML documents from disk files is one of the very interesting XML features available with SQL
Server. This is achieved by using the BULK row set provider for OPENROWSET. The following example shows how to load
the content of an XML file into an XML variable:
Пусть файл с именем c:\temp\ items.xml имеет следующее содержание
<Items>
<Item ItemNumber="1001" Quantity="1" Price="950"/>
<Item ItemNumber="1002" Quantity="1" Price="650" />
</Items>
Загрузка значения XML переменной данными из файла
DECLARE @xml XML
SELECT
@xml = CAST(bulkcolumn AS XML)
FROM OPENROWSET(BULK ‘C:\temp\items.xml’, SINGLE_BLOB) AS x
Запрос к переменной
SELECT
x.value(’@ItemNumber’,’CHAR(4)’) AS ItemNumber,
x.value(’@Quantity’,’INT’) AS Quantity,
x.value(’@Price’,’MONEY’) AS Price
FROM @xml.nodes(’/Items/Item’) i(x)
Результат выполнения запроса
ItemNumber
Quantity
Price
---------------------------------------1001
1
950.00
1002
1
650.00
•
•
•
•
Функция OPENROWSET(BULK. . .[filename, option]) может даже напрямую выполнять запрос к
данным в файле без их загрузки в таблицу или переменные.
Результат вызова данной функции может использоваться в качестве входных данных для
операций INSERT/UPDATE.
The following example queries the XML file directly:
SELECT
x.value(’@ItemNumber’,’CHAR(4)’) AS ItemNumber,
x.value(’@Quantity’,’INT’) AS Quantity,
x.value(’@Price’,’MONEY’) AS Price
FROM (
SELECT CAST(bulkcolumn AS XML) AS data
FROM OPENROWSET(BULK ‘C:\temp\items.xml’, SINGLE_BLOB)
AS x
)a
CROSS APPLY data.nodes(’/Items/Item’) i(x)
Результат выполнения запроса
ItemNumber
Quantity Price
-------------------1001
1
950.00
1002
1
650.00
---------------------
Другие встроенные методы типа
данных XML
Метод value()
• value() является одним из наиболее часто используемых методов XML
типа данных.
• Он используется для получения скалярного значения из XML документа,
хранимого в колонке таблицы.
• Он получает XQuery выражение выполняет его, формирует один узел,
преобразует его значение в заданный тип данных SQL Server и возвращает
полученное значение.
• Например:
DECLARE @x XML
SELEC @x = ‘<Order OrderID="1" OrderNumber="SO101" />’
SELECT
@x.value(’(Order/@OrderID)[1]’, ’INT’) AS OrderID,
@x.value(’(Order/@OrderNumber)[1]’, ’CHAR(5)’) AS OrderNumber
• Результат выполнения запроса
OrderID
OrderNumber
--------------------1
SO101
Метод nodes()
•
•
•
The nodes() method returns a row set representation of the XML document. An XQuery
operation can be performed on each node returned by the nodes() method. This is
useful when information has to be retrieved from all the nodes matching a specific
expression.
Here is an example:
DECLARE @x XML
SELECT @x = ‘
<Items>
<ItemNumber>1001</ItemNumber>
<ItemNumber>1002</ItemNumber>
</Items>’
SELECT
x.value(’.’, ’CHAR(4)’) AS ItemNumber
FROM @x.nodes(’/Items/ItemNumber’) o(x)
Результат выполнения запроса
ItemNumber
---------1001
1002
•
•
•
There is a slight difference between the way the query has to be written for XML variables and XML
columns. That’s because when working with an XML variable, only one XML document is processed at a
time; but when working with an XML column, several XML documents need to be processed in a single
batch.
This is usually achieved by using the CROSS APPLY operator.
The following example is a modified version of the preceding query that reads information from an XML
column:
SELECT
OrderID,
x.value(’@ItemNumber’,’CHAR(4)’) AS ItemNumber
FROM OrderXML
CROSS APPLY ItemData.nodes(’/Order/Item’) o(x)
•
Результат выполнения запроса
OrderID
ItemNumber
-------------------1
D001
1
Z001
2
D001
•
The CROSS APPLY operator joins each node returned by the nodes() method with the table, and the
value() method reads the ItemNumber value from each element returned by the nodes() method.
Метод exist()
• The exist() method checks whether an element or attribute
specified by a given XPath expression exists in the document.
• The following query uses the exist() method to filter rows that have
a specific item number:
SELECT OrderID
FROM OrderXML
WHERE ItemData.exist(’/Order/Item[@ItemNumber = "Z001"]’) = 1
OrderID
----------1
• The exist() method returns true (1) if an element or attribute with
the specified XPath expression exists in the XML document.
Метод modify()
• Метод modify()
– The modify() method is used to perform XML DML
operations on an XML document.
– It allows inserting, updating, or deleting XML
elements or attributes within an XML document.
Связывание XML вершин с
реляционными таблицами
•
•
•
SQL Server has extended the Relational Engine with XQuery capabilities. This offers a number of
advantages — for example, the query processor can evaluate relational and XQuery operations in a single
query. A single query plan is created with relational and XQuery operations, and results of a relational
query can be joined with XQuery results and vice versa.
Пример T-SQL запроса, связывающего XML вершины с обычными колонками таблицы:
SELECT oh.OrderID, c.Name AS Customer, i.ItemDescription AS Item,
x.value(’@Quantity’,’INT’) AS Quantity, x.value(’@Price’,’MONEY’) AS Price
FROM OrderHeader oh
INNER JOIN OrderXML ox ON ItemData.value(’(Order/@OrderID)[1]’,’INT’) = oh.OrderID
CROSS APPLY ItemData.nodes(’/Order/Item’) o(x)
INNER JOIN Customers c ON c.CustomerID = oh.CustomerID
INNER JOIN Items i ON i.ItemNumber = x.value(’@ItemNumber’,’CHAR(4)’)
Результат выполнения запроса
OrderID Customer Item
-------------------------1
Jacob Sebastian DELL XPS 1130 Laptop
1
Jacob Sebastian XBOX 360 Console
2
Jacob Sebastian DELL XPS 1130 Laptop
Quantity
------------
Price
------------1
900.00
1
200.00
1
900.00
Deleting with XML DML
• The following code shows an example of how it can be used:
DECLARE @myDoc XML
SET @myDoc = ‘<Person><FirstName>Joe</FirstName>
<LastName>Fawcett</LastName></Person>
‘SELECT @myDoc
SET @myDoc.modify(‘ delete /Person/*[2]‘)
SELECT @myDoc
• Результат:
<Person>
<FirstName>Joe</FirstName>
<LastName>Fawcett</LastName>
</Person>
Операции
• Функция modify()
• Удаление
delete(//item/alph[@name=”B”])
• Замена
replace value of old_expression with new_expression
• Вставка
insert new_node_expression (
{{{as first | as last} into} | after | before}
reference_node_expression )
CREATE TABLE SimpleBook
(BookId int IDENTITY(1,1) PRIMARY KEY
CLUSTERED, BookXml xml)
GO
INSERT SimpleBook
SELECT
'<book book_id="1">
<title>A Great Work</title>
<chapter chapter_id="1">
<title>An Excellent Chapter</title>
<section id="1">
<title>A Boring Section</title>
<paragraph para_id="1">
Something boring.
</paragraph>
</section>
<section id="2">
<title>Another Fine Section</title>
<paragraph para_id="2">
Another fine paragraph.
</paragraph>
</section>
</chapter>
</book>'
Содержание ячейки BookXML
<book book_id="1">
<title>A Great Work</title>
<chapter chapter_id="1">
<title>An Excellent Chapter</title>
<section id="1">
<title>A Boring Section</title>
<paragraph para_id="1">Something boring.</paragraph>
</section>
<section id="2">
<title>Another Fine Section</title>
<paragraph para_id="2"> Another fine paragraph. </paragraph>
</section>
</chapter>
</book>
• UPDATE SimpleBook
• SET BookXml.modify('replace value of
(/book/chapter/section[@id="1"]/title/text())[1] with
"A Fine Section"')
• WHERE BookId = 1
• GO
• UPDATE SimpleBook
• SET BookXml.modify('replace value of
(/book/chapter/section/paragraph[@para_id="1"]/text
())[1] with "A Fine Paragraph"')
• WHERE BookId = 1
<book book_id="1">
<title>A Great Work</title>
<chapter chapter_id="1">
<title>An Excellent Chapter</title>
<section id="1">
<title>A Fine Section</title>
<paragraph para_id="1"> A Fine Paragraph</paragraph>
</section>
<section id="2">
<title>Another Fine Section</title>
<paragraph para_id="2"> Another fine paragraph.</paragraph>
</section>
</chapter>
</book>
Download