699
.pdfдой строкой второй таблицы, давая тем самым в результате все возможные сочетания строк двух таблиц.
SELECT * FROM
Person CROSS JOIN City
или
SELECT * FROM
Person, City
Результат:
Person.Name |
Person.CityId |
City.Id |
City.Name |
Андрей |
1 |
1 |
Москва |
Андрей |
1 |
2 |
Санкт- |
|
|
|
Петербург |
Андрей |
1 |
3 |
Казань |
Леонид |
2 |
1 |
Москва |
Леонид |
2 |
2 |
Санкт- |
|
|
|
Петербург |
Леонид |
2 |
3 |
Казань |
Сергей |
1 |
1 |
Москва |
Сергей |
1 |
2 |
Санкт- |
|
|
|
Петербург |
Сергей |
1 |
3 |
Казань |
Григорий |
4 |
1 |
Москва |
Григорий |
4 |
2 |
Санкт- |
|
|
|
Петербург |
Григорий |
4 |
3 |
Казань |
Если в предложении WHERE добавить условие соединения (предикат p), т.е. ограничения на сочетания кортежей, то результат будет эквивалентен операции INNER JOIN с таким же условием:
SELECT * FROM
Person, City
181
WHERE
Person.CityId = City.Id
Таким образом, t1 CROSS JOIN t2 WHERE p и t1 INNER JOIN t2 ON p синтаксически являются альтернативными формами записи одной и той же логической операции внутреннего соединения по предикату p. Синтаксис CROSS JOIN + WHERE для операции соединения называют устаревшим, его не рекомендует стандарт SQL ANSI [20].
2.23. Использование XML в запросе в SQL-Server
Корпорация Microsoft усовершенствовала поддержку в SQL Server данных, описываемых на расширяемом языке разметки (Extensible Markup Language, XML), и программ-
ного кода из общеязыковой среды исполнения (Common Language Runtime, CLR) внутри БД.
Работа с XML
XML – это легко читаемый язык иерархической текстовой разметки, который обычно применяется для обмена данными в системах и между системами.
Язык XML применяется в операциях, связанных с БД:
•Извлечение реляционных данных в виде документа XML. Вместо получения таблицы данные записываются в документ XML.
•Передача данных в виде XML в БД. Вместо передачи
вБД скалярных значений с помощью выполнения множественных инструкций языка манипулирования данными (DML) или многократного выполнения хранимой процедуры можно передать в БД документ или фрагмент XML.
•Хранение или запрос действительного документа или фрагмента XML в БД.
Перед тем как приступить к работе с XML, нужно определиться, зачем нужны данные в таком формате. Причиной, по которой выбирается такой способ предоставления
182
данных, может быть то, что данные в таком формате лучше поддаются описанию как иерархии. Как правило, табличные данные сложно представить в виде иерархии. Например, чтобы вывести данные о заказах клиента (customerId=1,2), нужно использовать две таблицы. Можно последовательно составить запрос к таблице Customer и SalesOrderHeader либо выполнить запрос, соединив эти таблицы. Применение операторов Left outer join позволяет включить клиентов без заказов. Оператор order by позволяет последовательно вывести все заказы.
Такие данные трудно обозримы и создадут путаницу в клиентском приложении. Оба варианта создают большой объем работы в клиентском приложении. Решение с XML предпочтительнее, так как извлекает данные в виде иерархии (клиенты, имеющие заказы).
SELECT c.CustomerID AS '@id',c.CompanyName as'@name',
(select p.OrderDate as '@date', p.OrderID as '@Num' from Orders
p
where p.CustomerID=c.CustomerID for XML path('order')) as
'orders'
FROM Customers c
where c.CustomerID in ('a1','a2')
for XML path('customer'),root('customers')
Результат выполнения запроса:
<customers>
<customer id="a1 " name="Vesta"> <orders><order date="2014-09-
03T00:00:00" Num="1"/><order date="2014-09-02T00:00:00" Num="7"/></orders>
183
</customer>
<customer id="a2 " name="Luna"> <orders><order date="2014-09-
03T00:00:00" Num="11"/></orders> </customer>
</customers>
Если использовать этот запрос из приложения среды. NET и извлечь данные XML в память, то можно легко обрабатывать в цикле клиентов и соответствующие заказы.
FOR XML <режим>
В предыдущем примере для форматирования результата на языке XML в конец инструкции SELECT вставлено дополнительное предложение FOR XML. В языке SQL Server 2008 существуют четыре варианта, применяемые в предложении FOR XML: RAW, AUTO, EXPLICIT и PATH.
FOR XML RAW – простейшая реализация предложе-
ния FOR XML:
select c.CustomerId AS '@id', c.CompanyName as'@name'
from Customers c
where c.CustomerId in ('a1','a2') for XML raw;
Как правило, такой запрос возвращает почти каждую строку как элемент XML, а каждый столбец – как элемент
XML:
(<row Column1="…" Column1="…" />) <row _x0040_id="a1 "
_x0040_name="Vesta" />
<row _x0040_id="a2 " _x0040_name="Luna" />
FOR XML AUTO. Режим AUTO отличается от RAW
тем, что поддерживает иерархии. Однако иерархии должны быть простыми, так как режим AUTO не поддерживает разветвления. Поддерживается иерархия:
184
•Customer;
•Order;
•Order Row.
Не поддерживается следующая иерархия из-за наличия разветвления:
•Customer;
•Order;
•Order Row;
•Contacts.
В этом режиме таблица, включенная в запрос, получает собственный элемент иерархии, а имя элемента наследуется от псевдонима таблицы, используемого в запросе. Иерархия создается исходя из порядка столбцов, возвращенных запросом, а не из порядка столбцов в таблицах.
select cust.CustomerID AS '@id', cust.CompanyName
as'@name',ord.OrderID,ord.OrderDate from dbo.Orders as ord right outer
join
dbo.Customers as cust on cust.CustomerID=ord.CustomerID
where cust.CustomerID in ('a1','a2') order by ord.CustomerID for XML auto,
root('Customers');
Результат XML:
<Customers>
<cust _x0040_id="a1 " _x0040_name="Vesta">
<ord OrderID="1" OrderDate="2014-09- 03T00:00:00" />
<ord OrderID="7" OrderDate="2014-09- 02T00:00:00" />
</cust>
<cust _x0040_id="a2 " _x0040_name="Luna">
185
<ord OrderID="11" OrderDate="2014- 09-03T00:00:00" />
</cust>
</Customers>
FOR XML EXPLICIT. С помощью этого предложения можно вернуть результирующий набор. Для получения желаемого результата результирующий набор можно отсортировать. Результирующий набор должен содержать два столбца с именами: Tag и Parent. В столбец Tag вставляется целочисленный идентификатор для каждого элемента XML, который нужно вернуть, а в столбце Parent задается идентификатор из столбца Tag элемента XML, который является родительским для данного элемента. Если у элемента нет предка, в столбце Parent задается NULL. Остальные столбцы в результирующем наборе применяются для определения как имен, так и значений элементов и атрибутов, которые следует вернуть.
select 1 as tag
,null as Parent
,null as "Customers!1!!element"
,null as "Customer!2!Id"
,null as "Customer!2!Custname"
,null as "Order!3!Num"
,null as "Order!3!OrderDate"
,null as "Order!3!Quantity" union all
select 2 as tag
,1 as Parent
,null as "Customers!1!!element"
,c.CustomerID as "Customer!2!Id"
,c.CompanyName as "Customer!2!Custname"
,null as "Order!3!Num"
,null as "Order!3!OrderDate"
,null as "Order!3!Quantity"
from dbo.Customers as c
186
where c.CustomerID in ('a1','a2') union all
select 3 as tag
,2 as Parent
,null as "Customers!1!!element"
,p.CustomerID "Customer!2!Id"
,null as "Customer!2!Custname"
,p.OrderID as "Order!3!Num"
,p.OrderDate as "Order!3!OrderDate"
,p.OrderQuantity as "Order!3!Quantity"
from dbo.Orders as p
where p.CustomerID in ('a1','a2') order by "Customer!2!Id", tag
for XML Explicit;
Результат XML:
<Customers>
<Customer Id="a1 " Custname="Vesta"> <Order Num="1" OrderDate="2014-09-
03T00:00:00" Quantity="233" />
<Order Num="7" OrderDate="2014-09- 02T00:00:00" Quantity="233" />
</Customer>
<Customer Id="a2 " Custname="Luna"> <Order Num="11" OrderDate="2014-09-
03T00:00:00" Quantity="444" /> </Customer>
</Customers>
FOR XML Path. Это наилучший выбор для большинства решений. Режим Path позволяет интерпретировать имена заданных столбцов с помощью выражения XPath.
Select c.CustomerID AS '@id', c.CompanyName as'@name',
c.Phone as "additionalInfo/text()"
from dbo.Customers c
where c.CustomerID in ('a1','a2')
187
for XML path('customer'),root('customers')
Результат XML
<customers>
<customer id="a1 " name="Vesta"> <additionalInfo>>(212) 121-
9686</additionalInfo>
</customer>
<customer id="a2 " name="Luna"> <additionalInfo>(212) 121-
2122</additionalInfo>
</customer>
</customers>
Уданного режима гораздо больше возможностей, чем
урежимов RAW, AUTO, поскольку он позволяет добавлять в результат как атрибуты, так и подэлементы (вложенные элементы), а также заключать в него другие разновидности структур XML. Кроме того, его проще использовать, чем
PATH и EXPLICIT.
Вложение запросов FOR XML
Для создания иерархии все запросы с предложением FOR XML <режим> можно вкладывать друг в друга. Это означает, что для создания законченного документа XML можно поместить один запрос FOR XML в другой запрос
FOR XML.
Рассмотрим следующий запрос и результат:
Select c.CustomerID AS '@id',c.CompanyName as'@name',c.Phone as "additionalInfo/text()",
(select p.OrderDate as '@date', p.OrderID '@Num', p.OrderQuantity as '@Quantity',
(select t.ProductName as "@Tovar", t.Price as "@Price"
from dbo.Product t
188
where t.ProductId=p.ProductId |
|
|
||
for XML path('orderdetail'),type) |
|
|||
from dbo.Orders p |
|
|
||
where p.CustomerID=c.CustomerID |
as |
|||
for |
XML |
path('order'),type) |
||
'orders' |
|
|
|
|
from dbo.Customers c |
|
|
||
where c.CustomerID in ('a1','a2') |
|
|||
for XML path('customer'); |
|
|
||
Результат XML: |
|
|
|
|
<customer id="a1 " name="Vesta"> |
|
|
||
<additionalInfo>1217686</additionalInfo> |
|
|
||
<orders> |
|
|
|
|
<order |
date="2014-09-03T00:00:00" |
Num="1" |
||
Quantity="233"> |
|
|
|
|
<orderdetail Tovar="Журнал" Price="200.0000" /> |
|
|||
</order> |
|
|
|
|
<order |
date="2014-09-02T00:00:00" |
Num="7" |
||
Quantity="233"> |
|
|
|
|
<orderdetail Tovar="Журнал" Price="200.0000" /> |
|
|||
</order> |
|
|
|
|
</orders> |
|
|
|
|
</customer> |
|
|
|
|
<customer id="a2 " name="Luna"> |
|
|
||
<additionalInfo>(212) 121-2122</additionalInfo> |
|
|||
<orders> |
|
|
|
|
<order |
date="2014-09-03T00:00:00" |
Num="11" |
||
Quantity="444"> |
|
|
|
|
<orderdetail Tovar="Журнал" Price="200.0000" /> </order>
</orders>
</customer>
189
Применение типа данных XML
В SQL Server 2008 включен тип данных XML, который может использоваться для хранения фрагментов и документов XML. На внутреннем уровне тип данных XML хранится с помощью типа данных varbinary(max), т.е. XML сохраняется не как текстовая строка, а как двоичное представление документа или фрагмента XML.
Тип данных XML может быть типизированным и нетипизированным. Типизированный означает, что типу для проверки его содержимого присваивается коллекция схем
XML.
2.24. Вставка новой записи
Синтаксис оператора INSERT похож на синтаксис оператора SELECT. Его базовая форма имеет следующий вид:
INSERT [INTO] табли-
ца_или_представление [(список_столбцов)] VALUES (список_значений)
Каждый оператор INSERT может модифицировать только одну таблицу или представление. При использовании оператора INSERT для модификации представления следует учитывать следующие ограничения:
–представление не должно содержать функций агрегирования, таких как COUNT или AVG;
–представление не должно содержать операторов
TOP, GROUP BY, UNION или DISTINCT;
–представление не должно содержать вычисляемых столбцов;
–представление должно ссылаться на таблицу во фра-
зе FROM;
–оператор INSERT модифицирует столбцы только из одной таблицы.
190