МІНІСТЕРСТВО ОСВІТИ І НАУКИ УКРАЇНИ
НАЦІОНАЛЬНИЙ УНІВЕРСИТЕТ "ЛЬВІВСЬКА ПОЛІТЕХНІКА"
Інститут КНІТ
Кафедра ПЗ
ЗВІТ
До лабораторної роботи № 6
На тему: “ Тип даних XML, XQuery ”
З дисципліни : " Бази даних. Частина 2 "
Лектор:
Доцент
Павич Н.Я.
Мета роботи: Навчитися використовувати тип даних XML та використовувати XQuery для типу даних XML
Завдання до лабораторної роботи
Виконайте всі пункти і запишіть відповіді на поставлені в них питання.
Для користувацького типу даних (за варіантом) створіть структуру XML документа.
Створіть та каталогізуйте колекцію валідних (коректних) схем для цього типу.
Створіть таблицю із типом даних XML, продемонструйте інструкціями T-SQL роботу із XML типом даних та валідацією схем.
Продемонструйте роботу із XQuery для розглянутого стовпця із типом даних XML таблиці.
Варіант3:
Користувацькі типи даних (UDT): Викладач
Хід виконання завдання
Тип даних XML
xmltype.sql
create database xmldb
go
use xmldb
go
-- create table with xml type column
create table xmltable(
Id int primary key identity,
data xml
)
go
--
-- exercise 1
--
-- add a row, non-Unicode value
insert into xmltable values
('<book><author>Yur@</author></book>')
go
insert into xmltable values
('<?xml version="1.0" encoding="utf-8"?>
<book><author>Yur@</author></book>')
go
-- add a row, Unicode value
insert into xmltable values
(N'<book><author>Yur@</author></book>')
go
insert into xmltable values
(N'<?xml version="1.0" encoding="utf-8"?>
<book><author>Yur@</author></book>')
go
--Msg 9402, Level 16, State 1, Line 1
--XML parsing: line 1, character 38, unable to switch the encoding
-- select rows
select * from xmltable
go
--
-- exercise 2
--
-- empty element
insert into xmltable values
('<book/>')
go
-- empty element, textual difference
insert into xmltable values
('<book></book>')
go
-- select rows
select * from xmltable
go
-- supported encoding
insert xmltable values
('<?xml version="1.0" encoding="windows-1251"?><author>Yur@</author>')
go
-- unrecognized encoding
insert xmltable values
('<?xml version="1.0" encoding="unknown"?><author>Yur@</author>')
go
--Msg 9401, Level 16, State 1, Line 1
--XML parsing: line 1, character 40, unrecognized encoding
-- processing instruction and comment
insert xmltable values(
'<doc>
<?outofband data ?>
<!-- comment -->
<afterComment/>
</doc>')
go
select * from xmltable
go
--
-- exercise 3
--
-- non-wellformed document
insert xmltable values(
'<doc><overlap><o2></overlap></o2></doc>')
go
--Msg 9436, Level 16, State 1, Line 1
--XML parsing: line 1, character 28, end tag does not match start tag
-- xml fragment
insert xmltable values(
'<fragment>Sometext</fragment>
<fragment>Secondrootelement</fragment>')
go
-- select rows
select * from xmltable
go
--11 <fragment>Sometext</fragment><fragment>Secondrootelement</fragment>
insert xmltable values(
'Sometext')
go -- 12 Sometext
declare @x xml;
set @x = '<root><in>text</in></root>'
insert xmltable values(@x);
-- 13 <root><in>text</in></root>
xmlschema.sql
use master
go
create login fred with password = 'fredpass', default_database = xmldb
go
use xmldb
go
create user fred for login fred with default_schema = fred
go
create schema fred authorization fred
go
grant create xml schema collection to fred
go
setuser 'fred'
go
-- create xml schema collection
create xml schema collection XmlColl
as
N'<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:tns="urn:www-develop-com:invoices"
targetNamespace="urn:www-develop-com:invoices"
elementFormDefault="qualified">
<!-- named typedefs and element decls -->
<xsd:simpleType name="skuType">
<xsd:restriction base="xsd:integer" >
<xsd:minInclusive value="100" />
<xsd:maxInclusive value="999" />
</xsd:restriction>
</xsd:simpleType>
<xsd:complexType name="LineItem">
<xsd:sequence>
<xsd:element name="Sku" type="tns:skuType"/>
<xsd:element name="Description" type="xsd:string"/>
<xsd:element name="Price" type="xsd:double"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="LineItems">
<xsd:sequence>
<xsd:element name="LineItem" type="tns:LineItem" />
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="Invoice">
<xsd:sequence>
<xsd:element name="InvoiceID" type="xsd:string"/>
<xsd:element name="CustomerName" type="xsd:string"/>
<xsd:element name="LineItems" type="tns:LineItems"/>
</xsd:sequence>
</xsd:complexType>
<xsd:element name="Invoice" type="tns:Invoice"/>
</xsd:schema>'
go
setuser
go
-- table with a strongly typed column
-- type this by schema namespace
create table xmlinvoice(
Id int primary key identity,
data xml(fred.XmlColl)
)
go
-- insert
insert into xmlinvoice values('
<inv:Invoice xmlns:inv="urn:www-develop-com:invoices" >
<inv:InvoiceID>1000</inv:InvoiceID>
<inv:CustomerName>Jane Smith</inv:CustomerName>
<inv:LineItems>
<inv:LineItem>
<inv:Sku>134</inv:Sku>
<inv:Description>Dons Boxers</inv:Description>
<inv:Price>9.95</inv:Price>
</inv:LineItem>
</inv:LineItems>
</inv:Invoice>')
-- insert
insert into xmlinvoice values('
<inv:Invoice xmlns:inv="urn:www-develop-com:invoices" >
<inv:InvoiceID>1000</inv:InvoiceID>
<inv:CustomerName>Jane Smith</inv:CustomerName>
<inv:LineItems>
<inv:LineItem>
<!-- Sku cant be over 1000 -->
<inv:Sku>1134</inv:Sku>
<inv:Description>Dons Boxers</inv:Description>
<inv:Price>9.95</inv:Price>
</inv:LineItem>
</inv:LineItems>
</inv:Invoice>
')
go
select * from xmlinvoice
go
-- update
update xmlinvoice set data = '
<inv:Invoice xmlns:inv="urn:www-develop-com:invoices" >
<inv:InvoiceID>1000</inv:InvoiceID>
<inv:CustomerName>Jane Smith</inv:CustomerName>
<inv:LineItems>
<inv:LineItem>
<!-- Sku cant be over 1000 -->
<inv:Sku>1134</inv:Sku>
<inv:Description>Dons Boxers</inv:Description>
<inv:Price>9.95</inv:Price>
</inv:LineItem>
</inv:LineItems>
</inv:Invoice>'
where id = 1
go
-- one typed value
-- one untyped
declare @x xml
declare @y xml(fred.XmlColl)
-- set untyped to typed
set @x = '
<inv:Invoice xmlns:inv="urn:www-develop-com:invoices" >
<inv:InvoiceID>1000</inv:InvoiceID>
<inv:CustomerName>Jane Smith</inv:CustomerName>
<inv:LineItems>
<inv:LineItem>
<!-- Sku cant be over 1000 -->
<inv:Sku>1134</inv:Sku>
<inv:Description>Dons Boxers</inv:Description>
<inv:Price>9.95</inv:Price>
</inv:LineItem>
</inv:LineItems>
</inv:Invoice>' -- Command(s) completed successfully.
-- attempt to set schema validated value
set @y = @x
XQuery
constraint.sql
use xmldb
go
-- drop schema if it already exists
drop xml schema namespace 'urn:www-develop-com:invoices'
go
-- drop table if it already exists
drop table xmlinvoice
go
CREATE XML SCHEMA COLLECTION invoice_xsd
AS
N'
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:tns="urn:www-develop-com:invoices"
targetNamespace="urn:www-develop-com:invoices"
elementFormDefault="qualified">
<!-- named typedefs and element decls -->
<xsd:simpleType name="skuType">
<xsd:restriction base="xsd:integer" >
<xsd:minInclusive value="100" />
<xsd:maxInclusive value="999" />
</xsd:restriction>
</xsd:simpleType>
<xsd:complexType name="LineItem">
<xsd:sequence>
<xsd:element name="Sku" type="tns:skuType"/>
<xsd:element name="Description" type="xsd:string"/>
<xsd:element name="Price" type="xsd:double"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="LineItems">
<xsd:sequence>
<xsd:element name="LineItem" type="tns:LineItem" maxOccurs="unbounded"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="Invoice">
<xsd:sequence>
<xsd:element name="InvoiceID" type="xsd:string"/>
<xsd:element name="CustomerName" type="xsd:string"/>
<xsd:element name="LineItems" type="tns:LineItems"/>
</xsd:sequence>
</xsd:complexType>
<xsd:element name="Invoice" type="tns:Invoice"/>
</xsd:schema>'
go
-- table with a strongly typed column
-- type this by schema namespace
-- and an additional constraint
-- (big orders with more than 3 LineItems go into a different table)
create function CheckCount(@data xml)
returns bit
as
begin
return @data.exist('declare namespace inv="urn:www-develop-com:invoices";
//inv:Invoice/inv:LineItems/inv:LineItem[4]');
end
go
create table xmlinvoice(
id integer identity primary key,
invoice xml (invoice_xsd)
check(dbo.CheckCount(invoice) = 0 )
)
insert into xmlinvoice values('
<inv:Invoice xmlns:inv="urn:www-develop-com:invoices" >
<inv:InvoiceID>1000</inv:InvoiceID>
<inv:CustomerName>Jane Smith</inv:CustomerName>
<inv:LineItems>
<inv:LineItem>
<inv:Sku>134</inv:Sku>
<inv:Description>Dons Boxers</inv:Description>
<inv:Price>9.95</inv:Price>
</inv:LineItem>
</inv:LineItems>
</inv:Invoice>
')
go -- (1 row(s) affected)
insert into xmlinvoice values('
<inv:Invoice xmlns:inv="urn:www-develop-com:invoices" >
<inv:InvoiceID>1001</inv:InvoiceID>
<inv:CustomerName>John Jones</inv:CustomerName>
<inv:LineItems>
<inv:LineItem>
<inv:Sku>134</inv:Sku>
<inv:Description>Dons Boxers</inv:Description>
<inv:Price>9.95</inv:Price>
</inv:LineItem>
<inv:LineItem>
<inv:Sku>217</inv:Sku>
<inv:Description>COM is Love Teeshirt</inv:Description>
<inv:Price>14.95</inv:Price>
</inv:LineItem>
</inv:LineItems>
</inv:Invoice>
')
go -- (1 row(s) affected)
-- more than 3 LineItems, fails
insert into xmlinvoice values('
<inv:Invoice xmlns:inv="urn:www-develop-com:invoices" >
<inv:InvoiceID>1001</inv:InvoiceID>
<inv:CustomerName>John Jones</inv:CustomerName>
<inv:LineItems>
<inv:LineItem>
<inv:Sku>217</inv:Sku>
<inv:Description>COM is Love Teeshirt</inv:Description>
<inv:Price>14.95</inv:Price>
</inv:LineItem>
<inv:LineItem>
<inv:Sku>202</inv:Sku>
<inv:Description>Essential Yukon Book</inv:Description>
<inv:Price>39.95</inv:Price>
</inv:LineItem>
<inv:LineItem>
<inv:Sku>219</inv:Sku>
<inv:Description>Grey DM Teeshirt</inv:Description>
<inv:Price>14.95</inv:Price>
</inv:LineItem>
<inv:LineItem>
<inv:Sku>198</inv:Sku>
<inv:Description>Essential ADO.NET Book</inv:Description>
<inv:Price>49.95</inv:Price>
</inv:LineItem>
</inv:LineItems>
</inv:Invoice>
')
go
xmlvalue.sql
-- queries against the xmlinvoice table
use xmldb
go
select id, invoice.value('
declare namespace inv="urn:www-develop-com:invoices";
/inv:Invoice[1]/inv:InvoiceID[1]
',
-- SQL data type
'int') as invoiceid
from xmlinvoice
go
select id, invoice.value('
declare namespace inv="urn:www-develop-com:invoices";
sum(/inv:Invoice/inv:LineItems/inv:LineItem/inv:Price)
', 'money') as itemSum
from xmlinvoice
go
select id, invoice.value('
declare namespace inv="urn:www-develop-com:invoices"; count(/inv:Invoice/inv:LineItems/inv:LineItem/inv:Price)', 'int') as columnCount,
invoice.value('
declare namespace inv="urn:www-develop-com:invoices";
avg(/inv:Invoice/inv:LineItems/inv:LineItem/inv:Price)','money') as avgSum
from xmlinvoice
go
xmlquery.sql
-- using xml query
use xmldb
go
select invoice.query('
declare namespace inv="urn:www-develop-com:invoices";
for $invId in /inv:Invoice
for $invIt in $invId/inv:LineItems/inv:LineItem
return
<ListItems>
<InvoiceId> { data($invId/inv:InvoiceID[1]) } </InvoiceId>
<Sku> { data($invIt/inv:Sku[1]) } </Sku>
</ListItems>
') as xmldoc
from xmlinvoice
go
declare @d datetime
set @d = GETDATE()
select invoice.query('
declare namespace inv="urn:www-develop-com:invoices";
for $invId in /inv:Invoice
return
<Payments>
<InvoiceId> { data($invId/inv:InvoiceID[1]) } </InvoiceId>
<CustomerName> { data($invId/inv:CustomerName[1]) } </CustomerName>
<TotalSum> { data(sum($invId/inv:LineItems/inv:LineItem/inv:Price)) } </TotalSum>
<Date> { sql:variable("@d") } </Date>
</Payments>
') as xmldoc
from xmlinvoice
go
Структура XML документа для користувацького типу даних:
<teacher>
<name>Name</name>
<age>Age</age>
<subjects>
<subject>Subject1</subject>
<subject>Subject2</subject>
<subject>Subject3</subject>
</subjects>
</teacher>
Схема для користувацького типу даних:
create xml schema collection teacher_xsd
as
N'<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:tns="darkprogram-com-ua:employee"
targetNamespace="darkprogram-com-ua:employee"
elementFormDefault="qualified">
<xsd:simpleType name="AgeType">
<xsd:restriction base="xsd:integer" >
<xsd:minInclusive value="20" />
<xsd:maxInclusive value="90" />
</xsd:restriction>
</xsd:simpleType>
<xsd:complexType name="subjects">
<xsd:sequence>
<xsd:element name="subject" type="xsd:string" maxOccurs="unbounded"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="teacher">
<xsd:sequence>
<xsd:element name="name" type="xsd:string"/>
<xsd:element name="age" type="tns:AgeType"/>
<xsd:element name="subjects" type="tns:subjects"/>
</xsd:sequence>
</xsd:complexType>
<xsd:element name="teacher" type="tns:teacher"/>
</xsd:schema>'
go
Демонстрація роботи інструкцій T-SQL із XML типом даних та валідацією схем:
create table xmlteacher(
Id int primary key identity,
teacher xml(teacher_xsd)
)
go
-- insert
insert into xmlteacher values('
<yur:teacher xmlns:yur="darkprogram-com-ua:employee" >
<yur:name>Роман Іванович</yur:name>
<yur:age>38</yur:age>
<yur:subjects>
<yur:subject>Математика</yur:subject>
<yur:subject>Фізика</yur:subject>
</yur:subjects>
</yur:teacher>')
insert into xmlteacher values('
<yur:teacher xmlns:yur="darkprogram-com-ua:employee" >
<yur:name>Оксана Романівна</yur:name>
<yur:age>25</yur:age>
<yur:subjects>
<yur:subject>Англійська</yur:subject>
</yur:subjects>
</yur:teacher>')
insert into xmlteacher values('
<yur:teacher xmlns:yur="darkprogram-com-ua:employee" >
<yur:name> Роман Іванович </yur:name>
<yur:age>120</yur:age>
<yur:subjects>
<yur:subject> Математика </yur:subject>
<yur:subject> Фізика </yur:subject>
</yur:subjects>
</yur:teacher>')
insert into xmlteacher values('
<yur:teacher xmlns:yur="darkprogram-com-ua:employee" >
<yur:name> Оксана Романівна </yur:name>
<yur:AGE>25</yur:AGE>
<yur:subjects>
<yur:subject> Англійська </yur:subject>
</yur:subjects>
</yur:teacher>')
Робота із XQuery для розглянутого стовпця із типом даних XML таблиці:
select Id, Teacher.value('
declare namespace yur="darkprogram-com-ua:employee";
/yur:teacher[1]/yur:name[1]', 'nvarchar(100)') as teacherName,
Teacher.value('
declare namespace yur="darkprogram-com-ua:employee";
count(/yur:teacher/yur:subjects/yur:subject)', 'int') as subjectsCount
from xmlteacher
go
select Teacher.query('
declare namespace yur="darkprogram-com-ua:employee";
for $t in /yur:teacher
where $t/yur:age > 30
return
<Teacher>
<Name> { data($t/yur:name[1]) } </Name>
<Age> { data($t/yur:age[1]) } </Age>
<SubjectCount> {count(data($t/yur:subjects/yur:subject))} </SubjectCount>
</Teacher>
') as xmldoc
from xmlteacher
go
Висновок: на даній лабораторній роботі я ознайомився з тим як використовувати тип даних XML в Microsoft SQL Server 2008. Його можна використовувати для зберігання як простих XML даних без перевірки так і валідних даних, правильність яких звіряється відповідно до вказаної схеми. Для опрацювання XML даних було розглянуто засіб XQuery який дозволяє маніпулювати XML даними, отримувати значення окремих елементів чи атрибутів та формувати нові XML документи на основі існуючих.