Використання XML спільно з SQL h2>
XML і сучасні бази даних h2>
Олексій Ширшов p>
Вступ h2>
Цей матеріал присвячений тим нововведенням, які
з'явилися в SQL і технології доступу до баз даних завдяки XML. Стаття
описує базові механізми і можливості використання XML в MS SQL Server та
ADO. Стаття не претендує на фундаментальні дослідження в цій області, так
як XML і SQL Server речі по природі своїй неосяжні. Крім того, рівень підтримки
XML в SQL Server постійно збільшується, і за всіма змінами надзвичайно
важко встежити. Наприклад, після виходу SQLXML 3.0, стало можливим
використовувати SQL Server в якості сервера Web-служб. На жаль, ця тема в
статті не висвітлюється, але в майбутньому, можливо, знайдеться час і для неї. p>
Своєю появою стаття зобов'язана того безладу,
який був в голові у автора з даного питання. p>
Підтримка b> XML b> в b> Microsoft SQL Server 2000
b> p>
Microsoft SQL Server 2000 містить вбудовані засоби
для роботи з XML. Результуючу вибірку можна представляти у форматі XML з
допомогою ключових слів for xml оператора select, а також зробити запит з
документа XML з допомогою оператора OPENXML. p>
FOR XML
p>
Цей оператор призначений для представлення
результуючого набору рядків у вигляді XML-документа. Розглянемо його синтаксис: p>
[FOR (BROWSE | XML (RAW | AUTO | EXPLICIT) p>
[, XMLDATA] p>
[, ELEMENTS] p>
[, BINARY BASE64] p>
) p>
] p>
Призначення ключового слова BROWSE не відноситься до теми
нашої статті. p>
FOR XML RAW - Кожен рядок представляється у вигляді
елемента
. Назва поля формує назва атрибута, а значення
поля - значення атрибута. p>
FOR XML AUTO - Документ XML форматується точно так
само, як і при XML RAW, тільки назва елемента, що представляє рядок,
замінюється на назву таблиці. p>
FOR XML EXPLICIT - Самий складний і гнучкий варіант для
створення XML-документів. У цьому режимі можна формувати документи практично
будь-якої форми, однак для цього сам запит повинен бути написаний за певними
правилами. Більш докладно вони розглядаються нижче. p>
XMLDATA - Іноді буває корисно отримати не тільки
самі дані, але і їх схему. Схема даних також записується у форматі XML. Вона
визначає типи елементів і атрибутів, накладає обмеження на їх значення,
і взагалі являє метаінформації, що дозволяє перевірити документ на
дійсність (validity). Існує кілька різновидів (форматів)
схем даних. SQL Server використовує XDR-схеми (XML Data Reduced). Докладну
документацію по XDR можна знайти в [1]. Ключове слово XMLDATA може бути
використано для всіх трьох режимів формування XML-документа (raw, auto і
explicit). p>
ELEMENTS - Ключове слово, що використовується тільки
спільно з FOR XML AUTO. При його вказівці поля формуються як елементи:
назва поля відповідає назві елементу, а значення поля - значенням
елементу. p>
BINARY BASE64 - Визначає, як будуть виведені
двійкові дані (binary data). p>
ПОПЕРЕДЖЕННЯ p>
SQL Server не дозволяє використовувати
предикат GROUP BY спільно з FOR XML AUTO. p>
Приклади p>
Для простоти і зручності будемо використовувати стандартну
базу даних PUBS з поставки SQL Server 2000. Треба сказати, що Query Analyzer
- Не кращий засіб для перегляду XML-документів, тому що результат він поміщає в
одну клітинку, як текстове поле (або в один рядок, обрізаючи текст, при виведенні
результату у вигляді тексту). Тому, якщо ви хочете випробувати всі приклади
самі, зверніться до розділу IIS і XML-функції SQL Server. p>
Почнемо з розгляду FOR XML RAW: p>
select
au_fname, au_lname, address p>
from authors p>
where au_fname like 'M%' p>
for
xml raw p>
Цей запит повертає імена всіх авторів,
що починаються на літеру M. Ось результати в форматі XML: p>
p>
p>
P>
P>
P>
Тепер замінимо xml raw на xml auto: p>
p>
p>
P>
P>
P>
Як бачите, зміни невеликі. Замість назви
у вікні "row» підставляється ім'я таблиці. Тепер додамо до цього запиту
ключове слово ELEMENTS. p>
select
au_fname, au_lname, address p>
from authors p>
where au_fname like 'M%' p>
for
xml auto, elements p>
Ось результати: p>
p>
Marjorie au_fname> p>
Green au_lname> p>
309 63rd St.
# 411 address> p>
authors> p>
p>
Michael au_fname> p>
O'Leary au_lname> p>
22 Cleveland Av.
# 14 address> p>
authors> p>
p>
Meander au_fname>
p>
Smith au_lname> p>
10 Mississippi
Dr. Address> p>
authors> p>
p>
Morningstar au_fname>
p>
Greene au_lname> p>
22 Graybar House
Rd. Address> p>
authors> p>
p>
Michel au_fname> p>
DeFrance au_lname> p>
3 Balding
Pl. Address> p>
authors> p>
Документ вийшов більш громіздким: всі поля
представлені елементами. p>
За допомогою ключового слова XMLDATA можна отримати
документ зі схемою даних. p>
select
au_fname, au_lname, address p>
from authors p>
where au_fname like 'M%' p>
for
xml auto, xmldata p>
Цей запит поверне такий документ: p>
xmlns: dt = "urn: schemas-microsoft-com: datatypes"> p>
p>
p>
p>
p>
p>
P>
p>
ElementType> p>
Schema> p>
au_fname = "Marjorie"
au_lname = "Green" address = "309 63rd St. # 411" /> p>
au_fname = "Michael"
au_lname = "O'Leary" address = "22 Cleveland Av. # 14" /> p>
au_fname = "Meander"
au_lname = "Smith" address = "10 Mississippi Dr." /> P>
au_fname = "Morningstar"
au_lname = "Greene" address = "22 Graybar House Rd." /> p>
au_fname = "Michel"
au_lname = "DeFrance" address = "3 Balding Pl." /> p>
Як бачите, тепер документу передує ХDR-схема,
що дозволяє перевірити правильність його вмісту. p>
FOR XML EXPLICIT
p>
В даному режимі можна формувати практично будь-які
документи; структура результуючого XML-документа визначається безпосередньо
в самому запиті. Запит може приймати дуже складний вид, нижче будуть
розглянуті правила, за якими він складається. p>
Перше поле завжди називається tag і являє собою
числовий ідентифікатор таблиці. Ви можете вказувати для нього будь-які числові
значення. У результуючому документі він не з'являється, і потрібен тільки, щоб
визначити зв'язки між таблицями для формування ієрархічного документа.
Друге поле називається parent і теж може представляти будь-який числовий
ідентифікатор. Він визначає батьківську таблицю для даної таблиці і в
результуючому документі також не ходить. Якщо батьки відсутня,
вказується 0 або NULL. Для ієрархічних вибірок потрібно використовувати кілька
запитів, об'єднаних за допомогою оператора UNION ALL. p>
Після двох обов'язкових полів tag і parent слідують
поля, які потрібно вибрати з таблиці. Для них повинен бути заданий псевдонім,
визначає тип XML-вузла, його назва та іншу інформацію. Ось синтаксис
цього псевдоніма: p>
ElementName! TagNumber! AttributeName! Directive p>
Розглянемо призначення кожної з частин цього
псевдонім: p>
ElementName - ім'я елемента, в якому знаходиться
елемент даного поля. Зазвичай тут вказується ім'я таблиці. p>
TagNumber - ідентифікатор таблиці, в якій знаходиться
на цьому полі. Одному і тому ж ElementName завжди повинен відповідати один
TagNumber. Він також не відображається ні в якому вигляді в результуючому документі,
однак потрібен для визначення ієрархічних зв'язків між таблицями. p>
AttributeName - ім'я атрибута (або елемента),
представляє на цьому полі. p>
Directive - по суті, являє собою тип вузла.
Може приймати такі значення: p>
element p>
поле представляється у вигляді
елемента p>
xml p>
Те ж саме, що element,
але не виконує трансформації тексту. Наприклад, символ менше (<) не
перетворюється на посилання < p>
cdata p>
значення поля обрамляється
відповідним чином. Назва атрибуту вказувати разом із цим ключовим
словом не можна. p>
hide p>
дозволяє приховати поле p>
id, idref, idrefs p>
дозволяють робити посилання на
інші елементи. Ці атрибути мають значення, тільки якщо створюється схема
даних. p>
Розглянемо невеликий приклад. На самому початку ми
розглядали запит з використанням FOR XML RAW: p>
select
au_fname, au_lname, address from authors where au_fname like 'M%' for xml raw p>
Перепишемо його з використанням FOR XML EXPLICIT: p>
select
1 as tag, p>
0 as parent, p>
au_fname as 'authors! 1! fname', p>
au_lname as 'authors! 1! lname', p>
address as 'authors! 1! address' p>
from authors where au_fname like 'M%' p>
for
xml explicit p>
Результат буде точно таким же. Трохи виправимо
запит для демонстрації можливостей директиви FOR XML EXPLICIT. p>
select
1 as tag, p>
0 as
parent, p>
au_fname as 'authors! 1! fname', p>
au_lname as 'authors! 1! lname! element', p>
address as 'authors! 1!! cdata' p>
from authors where au_fname like 'M%' p>
for
xml explicit p>
Ось результат: p>
p>
Marjorie fname> p>
P>
authors> p>
p>
Michael fname> p>
p>
authors> p>
p>
Meander fname> p>
P>
authors> p>
p>
Morningstar fname> p>
P>
authors> p>
p>
Michel fname> p>
P>
authors> p>
Непогано для одного запиту! Оскільки для поля
au_lname вказаний атрибут element, вона подана у вигляді елементу. Адреса
знаходиться в секції CDATA. p>
Тепер розглянемо, як формувати ієрархічні
документи. Візьмемо такий запит: p>
select
pub_name, city, fname, lname p>
from publishers as p p>
join employee as e on p.pub_id = e.pub_id p>
where pub_name like 'Binnet%' or pub_name
like 'New Moon%' p>
order by pub_name, city, fname, lname p>
Він повертає імена всіх службовців видавництв Binnet
& Hardley і New Moon Books. Результат запиту (20 записів) я наводити не
буду, зазначу лише, що він містить велику кількість повторюваних назв
видавництв, тому що результат представлений в реляційної формі. Ми ж хочемо
отримати наступне: p>
p>
p>
p>
p>
p>
p>
p>
p>
p>
p>
p>
pubs> p>
p>
p>
p>
p>
p>
p>
p>
p>
p>
p>
p>
pubs> p>
І як, запитаєте ви? Приблизно так: p>
select 1 as tag, - перший підзапит p>
0 as parent, p>
pub_name as 'pubs! 1! PubName', p>
city as 'pubs! 1! City', p>
NULL as
'employee! 2! First_Name', p>
NULL as 'employee! 2! Last_Name' p>
from publishers as pubs p>
where pub_name like 'Binnet%'
or pub_name like 'New Moon%' p>
union all select 2 as tag, - друга підзапит p>
1 as parent, p>
pubs.pub_name, p>
pubs.city, p>
fname, p>
lname p>
from employee as e, publishers
as pubs p>
where (pub_name like 'Binnet%'
or pub_name like 'New Moon %') p>
and pubs.pub_id = e.pub_id p>
order by 'pubs! 1! PubName',
'pubs! 1! City', p>
'employee! 2! First_Name',
'employee! 2! Last_Name' p>
for xml explicit p>
Давайте розглянемо все по порядку. Спочатку виконується
перший підзапит. Його результат наведено в таблиці 1. P>
tag p>
parent p>
pubs! 1! PubName p>
pubs! 1! City p>
employee! 2! First_Name p>
employee! 2! Last_Name p>
1 p>
0 p>
New Moon Books p>
Boston p>
NULL p>
NULL p>
1 p>
0 p>
Binnet & Hardley p>
Washington p>
NULL p>
NULL p>
Таблиця 1. p>
Потім другий (Таблиця 2). p>
tag p>
parent p>
pub_name p>
city p>
fname p>
lname p>
2 p>
1 p>
Binnet & Hardley p>
Washington p>
Paolo p>
Accorti p>
2 p>
1 p>
Binnet & Hardley p>
Washington p>
Victoria p>
Ashworth p>
2 p>
1 p>
Binnet & Hardley p>
Washington p>
Helen p>
Bennett p>
2 p>
1 p>
Binnet & Hardley p>
Washington p>
Lesley p>
Brown p>
... p>
... p>
... p>
... p>
... p>
... p>
Таблиця 2. p>
Потім відбувається сортування, і на основі полів tag і
parent SQL Server формує ієрархічний XML документ. p>
ПРИМІТКА p>
Для налагодження подібних запитів краще не
вказувати оператор FOR XML EXPLICIT. Тоді дані будуть представлені в
звичайної реляційної формі. p>
На цьому ми, мабуть, закінчимо розгляд оператора
FOR XML EXPLICIT - приведення прикладів використання всіх атрибутів зайняло б
занадто багато місця. p>
OPENXML
p>
Функція OPENXML є аналогом OPENROWSET,
OPENDATASOURCE і OPENQUERY, які дозволяють виконувати запити з віддалених
джерел. Ось її синтаксис: p>
OPENXML (idoc
int [in], rowpattern nvarchar [in], [flags byte [in]]) p>
[WITH (SchemaDeclaration | TableName)] p>
Аргументи: p>
idoc - хендл XML-документа, отриманий за допомогою
збереженої процедури sp_xml_preparedocument; p>
rowpattern - локалізуемая група XPath або, простіше
кажучи, XPath-вираз; p>
flags - набір прапорів, які вказують на те, як повинні
бути порівняно дані документа XML і реляційного набору рядків; p>
ShemaDeclaration - визначення полів реляційного
набору рядків у форматі: p>
ColName ColType [ColPattern |
MetaProperty] p>
Де p>
ColName - ім'я поля. p>
ColType - тип поля. Допускаються всі типи SQL Server. p>
ColPattern - локалізуемая група XPath для поля. p>
MetaProperty - метасвойство. Його ми розглядати не
будемо. p>
XML-документ готується за допомогою збереженої
процедури sp_xml_preparedocument. Процедура використовує аналізатор MSXML для
перевірки документа на правильність і повертає хендл документа. Після
завершення роботи з OPENXML хендл потрібно закрити за допомогою процедури
sp_xml_removedocument. p>
ПРИМІТКА p>
sp_xml_preparedocument готує
XML-документ, представляючи його у вигляді об'єктної моделі DOM (Document Object
Model). Якщо ви працюєте з великими документами, це може викликати деякі
проблеми. p>
Як видно з синтаксису, ви можете не вказувати прапори
і визначення полів для реляційного набору рядків. У цьому випадку SQL Server
створить внутрішнє подання XML-документа у так званому "edge
table "-форматі. Він практично не читаємо, однак при великому бажанні його
можна використовувати. Опис цього формату виходить за рамки цієї статті, але в
Як доказ того, що з ним можна працювати, наведу приклад. Нехай у
нас є такий XML-документ: p>
xml version = "1.0" encoding = "windows-1251"
?> p>
p>
p>
description = "Системне програмування"> p>
p>
Alex
Fedotov top-poster> p>
forum> p>
description = "Компонентні технології"> p>
p>
Vi2 top-poster> p>
forum> p>
description = "Delphi і Builder"> p>
p>
p>
p>
moderators> p>
Sinclair top-poster> p>
forum> p>
p>
p>
p>
moderators> p>
Merle top-poster> p>
forum> p>
forums> p>
rsdn> p>
Ось запит, який повертає загальну кількість повідомлень
для кожного форуму: p>
exec
sp_xml_preparedocument @ hdoc out, @ _xmlbody p>
select
[text] as totalposts p>
from openxml (@ hdoc, '/ rsdn/forums/forum') as
f p>
join (select [id], localname p>
from
openxml (@ hdoc, '/ rsdn/forums/forum') p>
where localname = 'totalposts') as d on
d. [id] = f.parentid p>
exec
sp_xml_removedocument @ hdoc p>
Результатом його буде наступна таблиця: p>
totalposts p>
16688 p>
10116 p>
5001 p>
6606 p>
Не раджу використовувати подібний метод в рабочіх
проектах, і не тільки тому, що він неефективний (як видно з прикладу,
XML-документ сканується двічі). Розглянемо приклад, який видає той же самий
результат з використанням XPath. p>
exec
sp_xml_preparedocument @ hdoc out, @ _xmlbody p>
select
* P>
from openxml (@ hdoc, '/ rsdn/forums/forum') p>
with (totalposts varchar (100)
'attribute:: totalposts') p>
exec
sp_xml_removedocument @ hdoc p>
Тут, щоб обмежити Реляційний набір рядків, я
скористався XPath-виразом. p>
Вираз attribute:: totalposts означає, що для поля
totalposts буде використовуватися значення однойменного атрибуту. Набагато частіше в
XPath-виразах використовується скорочений запис: p>
«attribute::» можна замінити символом @; p>
«self:: node ()» можна замінити на крапку (.); p>
«parent:: node ()» можна замінити на дві точки (..). p>
Інші скорочення можна знайти в специфікації XPath. p>
Давайте розглянемо більш складний приклад: виберемо
назва форуму, модератора і дату створення статистики для всіх форумів, у
яких більше 6000 повідомлень. p>
exec sp_xml_preparedocument @ hdoc out, @ _xmlbody p>
select p>
forum as 'Форум', p>
case when moders is null p>
then 'немає' p>
else moders p>
end as 'Модератор', p>
[date] as 'Дата створення' p>
from
openxml (@ hdoc, '/ rsdn/forums/forum [attribute:: totalposts>
"6000"] ') with p>
( p>
moders varchar (50)
'moderators/moderator/attribute:: name', p>
forum varchar (50)
'attribute:: name', p>
[date] varchar (50)
'parent:: node ()/attribute:: date' p>
) p>
exec sp_xml_removedocument @ hdoc p>
Частина запиту, що використовує XPath, можна переписати в
скороченій формі: p>
openxml (@ hdoc, '/ rsdn/forums/forum [@ totalposts> "6000"]')
with p>
( p>
moders varchar (50)
'moderators/moderator/@ name', p>
forum varchar (50) '@ name', p>
[date] varchar (50)'../date ' p>
) p>
Скрізь далі я буду користуватися скороченим записом. p>
Щоб розібратися з прапорами OPENXML, розглянемо злегка
модифікований приклад з MSDN: p>
DECLARE @ idoc int p>
DECLARE @ doc varchar (1000) p>
SET @ doc = ' p>
p>
p>
Janine name> p>
p>
p>
Customer was very satisfied p>
Order> p>
Customer> p>
p>
Ursula name> p>
Happy
Customer. Order> p>
note = "Wrap it
blue white red "> p>
Sad Customer. p>
Important Urgency> p>
Order> p>
Customer> p>
root> ' p>
- Створення внутрішнього
подання XML-документа. p>
EXEC sp_xml_preparedocument @ idoc OUTPUT, @ doc p>
SELECT * p>
FROM OPENXML (@ idoc,
'/ root/Customer', 2) WITH p>
( p>
cid char (5) '@ cid', p>
[name] varchar (20), p>
oid char (5) 'Order/@ oid', p>
amount float 'Order/@ amount', p>
comment varchar (100)
'Order/text ()' p>
) p>
- Очищення p>
EXEC sp_xml_removedocument @ idoc p>
Результат буде наступним: p>
cid p>
name p>
oid p>
amount p>
comment p>
C1 p>
Janine p>
O1 p>
3.5 p>
Customer was very satisfied p>
C2 p>
Ursula p>
O4 p>
10000.0 p>
Happy Customer. p>
Відзначимо деякі особливості: p>
Як режим відображення XML-даних на поля
реляційної таблиці використовувалося значення 2 (element-centric mapping). Це
означає, що за замовчуванням імена колонок одержуваної реляційної таблиці будуть
відповідати іменам вкладених XML-елементів. Крім цього, можливо
використання значень 0, 1 і 8. 0 використовується за умовчанням і означає
використання attribute-centric mapping. 1, як не дивно, означає те ж
саме. Прапори 1 і 2 можна комбінувати за "або", тобто якщо підставити
3, спочатку буде зроблено спробу знайти атрибут з ім'ям, відповідним
імені колонки, а потім (якщо атрибут не знайдено) буде проведений пошук елемента
з відповідним ім'ям (інакше буде повернуто NULL). Завдяки тому, що в
як прапора було вказано значення 2, для поля cid довелося явно вказати
XPath-запит, який вказує, що на цю колонку відображається атрибут cid. Для
поля name не треба було безпосереднього зазначення XPath-вирази. Якщо б
в якості прапора використовувалося значення 1 (використання відображення
атрибутів), то картина змінилася б на протилежну: тобто для cid не потрібно
б було нічого вказувати, а для name довелося б написати шаблон (тобто просто
вираз 'name'). p>
Особливість застосування XPath-виразів при відображенні
даних полягає в тому, що можлива вибірка даних, розташованих практично в
будь-якої частини XML-документа (щодо поточної гілки). Так, можна звернутися до
подветкам поточної гілки, батьківським гілках, і навіть отримати дані на основі
виконання деякого умови. Якщо б замість «comment varchar (100)
'Order/text ()' »було написано« comment varchar (100) 'Order' », то колонка
comment першого рядка містила б пустий рядок. Вона бралася б з першого
замовлення (O1). Але так як тексту в цьому елементі немає, функція text () поверне
для нього false, що призведе до пошуку тексту наступного по порядку елементі
Order (замовленні O2). Таким чином, в сформованій запису буде знаходитися
інформація з першого замовлення і коментар з другого. Прикладного сенсу це
дія не має, але чудово демонструє гнучкість техніки відображення. p>
На цьому ми з вами закінчимо розгляд конструкції
OPENXML. Більш детальну інформацію можна отримати в MSDN. Специфікацію XPath
можна знайти в [2]. p>
IIS і XML функції SQL Server
p>
Щоб виконувати запити до SQL Server через HTTP,
необхідно налаштувати відповідним чином інтернет-сервер. Робиться це з
допомогою майстра "Configure SQL XML Support in IIS". Я не буду
описувати повністю його роботу, при необхідності можете звернутися до [3]. Крім
цього, настроїти віртуальний каталог можна програмно за допомогою об'єкта
VDirMgr. Він знаходиться у файлі sqlvdr3.dll. Для використання класу з VB потрібно
додати посилання на бібліотеку типів Microsoft SQL Virtual Directory Control 1.0
Type Library. p>
Майстер "Configure SQL XML Support in IIS"
створює віртуальний каталог, для обробки запитів до якого призначається
спеціальне isapi-розширення: sqlisapi.dll. Ця бібліотека, використовуючи провайдер
SQL OLEDB, зв'язується з SQL Server для відправлення запитів і отримання
результатів. Результуючі вибірки, представлені вже у форматі XML,
передаються назад викликає стороні по HTTP. За допомогою майстра ви можете
вказати: p>
Обліковий запис SQL Server або Windows, під якою
виконуватимуться всі запити; p>
Комп'ютер, на якому розташований SQL Server і базу
даних; p>
підкаталоги даного віртуального каталогу для зберігання
різних типів файлів (шаблонів, схем). Підкаталоги можуть бути трьох
визначених типів: schema, template і dbobject. У підкаталозі schema
зберігаються XDR або XSD схеми даних, які можна безпосередньо виконувати в
URL-запиті. У підкаталозі з типом template зберігаються шаблони, виконання
яких дозволено через URL-запити. dbobject - псевдокаталог, його ми
розглядати не будемо. p>
ПРИМІТКА p>
У SQLXML 3.0 з'явився ще один тип
підкаталогів - soap. Його розгляд також виходить за рамки цієї статті. P>
Окремо зупинимося на настройках каталогу. Ви
можете: p>
Дозволити або заборонити вказувати SQL-інструкції
безпосередньо в URL. Відзначу, що в якості інструкцій можна використовувати не
тільки запити, але і будь-які інші оператори. Раджу встановлювати цю опцію
тільки для налагодження, а в нормальному режимі роботи вимикати. p>
Дозволити або заборонити виконання запитів,
що зберігаються у спеціальних шаблонах. Детальніше про шаблони буде сказано далі. p>
Дозволити або заборонити використання запитів XPath; p>
Дозволити або заборонити використовувати метод POST. p>
URL-запити
p>
Розглянемо синтаксис URL-запиту до SQL Server: p>
http://iisserver/vroot?sql=sqlinstruction [& param = value [& param = value] ... n] p>
Тут: p>
iisserver - ім'я інтернет-сервера; p>
vroot - ім'я віртуального каталогу; p>
sqlinstruction - будь-яка SQL-інструкція; p>
param - ім'я параметра. Це не параметр SQL-інструкції
або збереженої процедури, це параметр шаблону або один з наступних
зумовлених параметрів: contenttype, outputencoding, root і xsl; p>
value - значення параметра. p>
Отже, припустимо, ви настроїти віртуальний
каталог для використання бази даних PUBS і назвали його server_pubs. Покладемо,
ваш комп'ютер називається server. Спробуємо написати першим URL-запит: p>
http://server/server_pubs/?sql=select
au_fname, au_lname, address from authors where au_fname like 'M%' for xml raw p>
Але не все так просто. Відповідь буде таким: p>
XML
document must have a top level element. p>
Перший млинець, як завжди, комом! Справа в тому, що
XML-документ, що формується SQL Server'ом, не має головного кореневого елемента,
без якого документ не може вважатися правильно оформленим. Для вказівки
кореневого елемента потрібно додати параметр root. p>
http://server/server_pubs/?sql=select
au_fname, au_lname, address from authors where au_fname like 'M%' for xml
raw & root = my_root p>
У відповідь буде видано: p>
Incorrect syntax near 'M'. p>
Що ж, досвідчені користувачі, напевно, відразу б
примітили знак відсотка у запиті. Він є зарезервованим символом у
імені URL, його код дорівнює 25. З огляду на це, перепишемо запит так: p>
http://server/server_pubs/?sql=select
au_fname, au_lname, address from authors where au_fname like 'M% 25' for xml
raw & root = my_root p>
Ура! Вийшло. Результат буде приблизно таким же,
як в самому першому прикладі цієї статті. p>
На випадок, якщо вам потрібно отримати результати у вигляді
звичайного HTML, можна створити шаблон перетворення мовою XSL і вказати ще
один параметр в URL - xsl. У якості значення параметра потрібно вказати шлях
щодо вибраної вами віртуальної директорії. p>
Складемо шаблон трансформації: p>
xml version = "1.0"?> p>
version = "1.0"> p>
p>
p>
p>
xsl: template> p>
p>
p>
p>
td> p>
| . td> p>
| Address:
td> p>
tr> table> p>
li> p>
xsl: template> p>
p>
p>
p>
p>
p>
ul> p>
body> p>
html> p>
xsl: template> p>
xsl: stylesheet> p>
Більш докладну інформацію про XSL можна знайти в [4]. p>
У відповідь на наступний URL-запит ви отримаєте
перетворений XML-документ. p>
http://server/server_pubs/?sql=select
au_fname, au_lname, address from authors where au_fname like 'M% 25' for xml
raw & root = my_root & xsl = xsl_for_query.xsl p>
Насправді робота з URL-запитами цікава тільки
перші кілька хвилин. Дійсно, дуже незручно возитися з рядком
адреси і нескінченними символами відсотка в ній, до того ж URL-запити не дуже
гарні в сенсі безпеки. Альтернативою їм є шаблони. P>
Шаблони
p>
Шаблони в контексті цієї статті є звичайними
XML-документами, складеними за певними правилами. Основним їх
змістом є SQL-запит або виклик збереженої процедури. Шаблони також
використовуються для запитів XPath, проте їх я Щодо трохи пізніше. Параметри
шаблону задаються в URL-рядку. Якщо вони там не вказані, беруться значення за
замовчуванням з відповідних тегів . p>
Шаблони зберігаються на сервері, тому в сенсі
безпеки їх використання набагато кращий, ніж URL-запитів. Щоб
ISAPI-розширення, яка їх обробляє, зрозуміло, що ви викликаєте шаблон, його
потрібно помістити в свій віртуальний каталог. Зазвичай він називається template. Налаштувати
його можна в згадуваному раніше майстра "Configure SQL XML Support in
IIS "на закладці Virtual Names. P>
Структура шаблону виглядає так: p>
xml version = "1.0"?> p>
sql: xsl = "xsl file
name "> p>
p>
param_value sql: param> p>
param_value sql: param> ... n p>
xql: header> p>
p>
будь-який SQL-вираз p>
sql: query> p>
your_root> p>
Для форматування результатів виконання шаблону
може бути використана XSL-трансформація. Для цього необхідно задати атрибут
xsl, значення якого є відносний або повний шлях до файлу, який містить
шаблон трансформації. Атрибут xsl необов'язковий, як і розділ header. p>
Ось як буде виглядати шаблон, заснований на добряче
вже набридлому вам запиті. p>
xml version = "1.0"?> p>
sql: xsl = "xsl_for_query.xsl"> p>
p>
select
au_fname, au_lname, address p>
from authors where au_fname
like 'M%' for xml raw p>
sql: query> p>
my_root> p>
У ньому використовується та ж схема перетворення, що й у
попередньому прикладі. Тепер спробуйте його викликати (припустимо, ви його
зберегли під ім'ям first_template.xml): p>
http://server/server_pubs/template/first_template.xml p>
Результат виходить досить дивним: IE
представляє HTML-документ (отримується при трансформації) у форматі XML. Робить
він це на цілком законних підставах, і щоб результат видавався все-таки в
форматі HTML, потрібно явно вказати тип вихідного потоку. Це легко зробити за
допомогою параметра contenttype. p>
http://server/server_pubs/template/first_template.xml?contenttype=text/html p>
шаблонів Переваги очевидні: p>
Так як шаблон знаходиться на сервері, ви повністю
контролюєте його вміст; p>
Шаблони набагато простіше у використанні; p>
Тіло шаблону і використовується схема перетворення
приховані від користувача; p>
Шаблони можна динамічно змінювати або створювати, що
надає інтернет-серверу додаткову гнучкість; p>
За допомогою шаблонів можна виконувати запити XPath, але
про це вже в наступному розділі. p>
У шаблонах можна використовувати наступні атрибути
(розглянуті найбільш використовувані): p>
client-side-xml - Булева змінна, що приймає
значення 0 або 1. Якщо вказується 1, то при вибірці використовується форматування
XML-документа на клієнті. Тобто SQL Server виконує звичайний запит, передає
рекордсет клієнту, і вже там проводиться формування документа. Більше
докладно клієнтські курсори будуть розглянуті в розділі ADO і XML. p>
ПРИМІТКА p>
В даному випадку є клієнтом
комп'ютер, звідки надходить запит до SQL Server-y, то є машина, де
розташований SQLXMLOLEDB-провайдер. У разі використання ADO - це машина
клієнта. У разі використання шаблонів - сервер IIS. P>
nullvalue - дозволяє задавати рядок, який в
URL-запиті, а також запит XPath буде означати NULL. p>
is-xml - атрибут параметра, що приймає значення 0 і
1, використовується в розділі header. За замовчуванням він дорівнює 1. Це означає, що
значення параметра інтерпретується як фрагмент xml, тому, наприклад,
<не замінюється. Якщо встановлено значення 0, параметр інтерпретується як
звичайний текст. p>
Призначення інших атрибутів можна знайти в MSDN. p>
Запити XPath
p>
XPath не розрахований на роботу з реляційними даними.
Для використання XPath-запити для вибірки реляційних даних, необхідно
створити схему даних XDR або XSD. XDR було розроблено кілька років тому при
активній участі Microsoft, тому що в той час необхідність у схемах даних була,
а, по суті, самих схем не було. З появою XSD популярність і
актуальність застосування XDR почали падати. p>
ПРИМІТКА p>
Специфікацію XSD можна знайти в [5]. p>
Схема даних виконує дві важливі функції: задає
структуру майбутнього XML-документа і визначає, які поля і таблиці повинні
використовуватися при виконанні запиту XPath. Такі схеми називаються
анотований схемами запитів, а атрибути, що зв'язують об'єкти бази даних з
XML-вузлами - анотаціями. До виходу в світ SQLXML 2.0 можна було використовувати
тільки анотовані схеми на основі SDR [6]. Однак зараз краще використовувати
анотовані схеми на основі специфікації XSD [7]. Деяку інформацію з
перетворенню схем з XDR в більш новий формат XSD можна знайти в [8]. p>
Ось синтаксис шаблонів з використанням запитів
XPath: p>
p>
p>
param_value sql: param> p>
param_value sql: param> ... n p>
sql: header> p>
p>
XPath query p>
sql: xpath-query> p>
your_root> p>
У цьому прикладі анотована схема повинна знаходиться в
фото your_schema.xml. Як видно з синтаксису, можливе створення
параметризованих запитів XPath. Параметр у запиті позначається початковим
символом $. p>
Розглянемо приклад анотованої схеми XDR, який
використовуватиметься для запитів XPath. У результуючому документі будуть
бути присутнім імена, прізвища та адреси всіх авторів: p>
xml version = "1.0"?> p>
xmlns: sql = "urn: schemas-microsoft-com: xml-sql" p>
xmlns: dt = "urn: schemas-microsoft-com: datatypes"> p>
p>
p>
p>
p>
p>
p>
p>
ElementType> p>
Schema> p>
Тут використовується анотація relation для того, щоб
вказати, з якою таблицею буде пов'язаний елемент Authors. Дочірні елементи
успадковують зв'язок з таблицею, зазначеної для батьківського ElementType. Пов'язувавие
полів таблиці або подання (view) можна виконувати явно, з використанням
анотації field. У даному прикладі для елементів AttributeType цього робити не
потрібно, тому що відображення на відповідні поля виконуються автоматично.
Однак для дочірніх елементів ElementType, які за умовчанням зв'язуються з
таблицями, така анотація може бути необхідна. Найбільш часто використовувані
анотації наведені далі. p>
Тепер можна перейти до самого шаблону. Припустимо,
анотований схему ви зберегли під ім'ям MySchema.xml. p>
ПРИМІТКА p>
IIS розрізняє тип XML-документа тільки
на основі каталогу, де він знаходиться. Навіть якщо ми не налаштували спеціальним
чином IIS на виконання схем, їх краще зберігати в одному місці. Я рекомендую
зберігати схеми та шаблони в різних віртуальних каталогах. Наприклад, template
для шаблонів, schema - для схем. p>
Ось так виглядає шаблон, що вибирає імена, прізвища та
адреси всіх авторів: p>
p>
p>
/Authors p>
sql: xpath-query> p>
my_root> p>
Так як схеми XDR поступово витісняються схемами XSD,
перепишемо приклад з використанням XSD. p>
ПОПЕРЕДЖЕННЯ p>
Я півтора дня втратив, коли перший раз
намагався виконати запит XPath на XSD-схемі. ISAPI-розширення наполегливо видавало помилку «XPath: unable
to find/authors in the schema ». У
Зрештою, після нетривалих консультацій з одним із учасників
форуму сайту www.sql.ru, проблема була вирішена. Суть її в наступному: при
створення віртуального каталогу я використав оснащення mmc SQL IIS Admin.MSC,
яка входить до стандартного комплекту MS SQL Server'а і нічого не знає про
нові можливості SQLXML 3.0. Нова оснащення лежить в% Program Files% SQLXML
3.0 і називається sqlisad3.msc. Її можна запустити з меню Start-> Programs-> SQLXML
3.0-> Configure IIS Support. Завжди користуйтеся тільки нею. P>
Ось список основних відмінностей XDR від XSD [9], до якого
я дуже часто звертаюся: p>
XDR p>
XSD p>
Schema p>
schema p>
ElementType p>
element p>
AttributeType p>
attribute p>
attribute p>
none p>
З урахуванням цього схема буде виглядати так: p>
xmlns: sql = "urn: schemas-microsoft-com: mapping-schema"> p>
p>
p>
p>
p>
p>
xsd: complexType> p>
xsd: element> p>
xsd: schema> p>
Тут явно вказані анотації, що дозволяють зв'язати
XML-елементи до таблиці authors та відповідними полями. У цьому випадку все
вони не обов'язкові, тому що SQLXML може вивести зв'язку з назв вузлів. Ось
приклад, де анотації дійсно необхідні. Для різноманітності адресу і
прізвище винесені в окремі елементи: p>
xml
version = "1.0" encoding = "windows-1251"?> p>
xmlns: sql = "urn: schemas-microsoft-com: mapping-schema"> p>
p>
p>
p>
p>
|
|