【SQL Server学习笔记】XML、分层、空间数据

1、XML

xml数据可以组成为多个属性,或者多个项目

CREATE DATABASE Test

USE TEST
GO

drop table dbo.book

create table dbo.book
	(BookID int identity(1,1) primary key,
	 BookNM char(100) not null,
	 AuthorID int not null,
	 ChapterDESC XML null
	)
go


--1.非类型化XML
declare @book xml

set @book = 
	CAST('<book name="sql server 2000 fast answers">
	     <chapters>
	     <chapter id="1">Installation,Upgrades...</chapter>
	     <chapter id="2">Configuring SQL Server</chapter>
	     <chapter id="3">Creating and Configuring Databases</chapter>
	     <chapter id="">SQL Server Agent and SQL Logs</chapter>
	     </chapters>
	     </book>' as XML
	    )

insert into dbo.book(BOOKNM,AUTHORID,CHAPTERDESC)
values('sql server',
       55,
       @book)


--2.创建XML架构
CREATE XML SCHEMA COLLECTION BOOKSTORECOLLECTION
AS
N'<xsd:schema targetNamespace="http://ggg/bookstore"
   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" />
	 
	  <xsd:element name="bookxml">
		<xsd:complexType>		
			<xsd:sequence>
			
				<xsd:element name="bookname" minOccurs="0">
					<xsd:simpleType>
						<xsd:restriction base="sqltypes:varchar">
						<xsd:maxLength value="50" />
						</xsd:restriction>
					</xsd:simpleType>
				</xsd:element>
				
				<xsd:element name="ChapterID" type="sqltypes:int" minOccurs="0" />
				
				<xsd:element name="ChapterNM" minOccurs="0">
					<xsd:simpleType>
						<xsd:restriction base="sqltypes:varchar">
						<xsd:maxLength value="50" />
						</xsd:restriction>
					</xsd:simpleType>
				</xsd:element>		
				
			</xsd:sequence>			
		</xsd:complexType>	    
	  </xsd:element>	
</xsd:schema>	
'


--3.类型化xml
create table dbo.bookXML
	(BookID int identity(1,1) primary key,
	 BookNM char(100) not null,
	 ChapterID int not null,
	 ChapterDESC XML (bookStoreCollection) null --类型化xml
	)

declare @bookxml xml(bookstorecollection)

set @bookxml ='<bookxml xmlns="http://ggg/bookstore" >
               <bookname>sql</bookname>
               <ChapterID>123</ChapterID>
               <ChapterNM>sqlwc</ChapterNM>
               </bookxml>
               '

insert into bookXML(BookNM,ChapterID,ChapterDESC)
values('sql server 2008',123,@bookxml)     

select * from bookXML


--4.1查看xml架构
select *
from SYS.xml_schema_collections

--4.2查看命名空间
select n.*,
       c.*
from sys.xml_schema_namespaces n
inner join sys.xml_schema_collections c
        on n.xml_collection_id = c.xml_collection_id


--4.3删除xml架构
drop xml schema collection bookstorecollection

获取数据

create table dbo.bookInvoice
	(bookInvoiceID int identity(1,1) primary key,
	 bookinvoiceXML xml not null)
	 

insert into bookInvoice(bookinvoiceXML)
values('<bookinvoice invoicenumber="1" customerid="22" orderdate="2008-07-01">
        <orderitems>
        <item id="22" qty="1" name="sql fun in the sun" />
        <item id="24" qty="1" name="t-sql crossword puzzles" />
        </orderitems>
        </bookinvoice>')

insert into bookInvoice(bookinvoiceXML)
values('<bookinvoice invoicenumber="1" customerid="40" orderdate="2008-07-11">
        <orderitems>
        <item id="11" qty="1" name="MCDBA Cliff Notes" />
        </orderitems>
        </bookinvoice>')
        
insert into bookInvoice(bookinvoiceXML)
values('<bookinvoice invoicenumber="1" customerid="9" orderdate="2008-07-22">
        <orderitems>
        <item id="11" qty="1" name="MCDBA Cliff Notes" />
        <item id="24" qty="1" name="t-sql crossword puzzles" />
        </orderitems>
        </bookinvoice>')

--exist方法
select bookInvoiceID
from dbo.bookInvoice
where bookinvoiceXML.exist(
                    '/bookinvoice/orderitems/item[@id=11]') = 1


--nodes方法、value方法
declare @bookxml xml

select @bookxml = bookinvoiceXML
From dbo.bookInvoice
where bookInvoiceID = 1
                          
select bookId.value('@id','integer')
from @bookxml.nodes(
              '/bookinvoice/orderitems/item') as booktable(BookID)
              

--query方法
declare @v xml

select @v = bookinvoiceXML
from dbo.bookInvoice
where bookInvoiceID = 1

select @v.query('/bookinvoice/orderitems')    


--value方法,一次只能处理一个值,所以这里加了[1]来限制只取返回结果集的第一行
--[2]限制只取返回结果集的第二行
select  
       bookinvoicexml.value(
                '(/bookinvoice/orderitems/item/@name)[1]',
                'varchar(30)') as titles
from dbo.bookInvoice

union

select  
       bookinvoicexml.value(
                '(/bookinvoice/orderitems/item/@name)[2]',
                'varchar(30)')
from dbo.bookInvoice
          

 修改数据

--通过modify方法插入一geitem
update dbo.book
set ChapterDESC.modify
('insert <chapter id="5">SQL SERVER INTERNALS</chapter>
  into (/book/chapters)[1]')

select * from dbo.book
  


建立XML索引

可以使用xml索引提高xml数据类型列的查询性能,表 必须已经在主键上定义了聚集索引。xml列只能建立一个主xml索引,以及最多3个辅助。

Create XML Index 
CREATE [ PRIMARY ] XML INDEX index_name 
    ON <object> ( xml_column_name )
    [ USING XML INDEX xml_index_name 
        [ FOR { VALUE | PATH | PROPERTY } ] ]
    [ WITH ( <xml_index_option> [ ,...n ] ) ]
[ ; ]

<object> ::=
{
    [ database_name. [ schema_name ] . | schema_name. ] 
        table_name
}

<xml_index_option> ::=
{ 
    PAD_INDEX  = { ON | OFF }
  | FILLFACTOR = fillfactor
   | SORT_IN_TEMPDB = { ON | OFF }
    | IGNORE_DUP_KEY = OFF
  | DROP_EXISTING = { ON | OFF }
  | ONLINE = OFF
  | ALLOW_ROW_LOCKS = { ON | OFF }
  | ALLOW_PAGE_LOCKS = { ON | OFF }
  | MAXDOP = max_degree_of_parallelism
}

 

--1.建立主xml索引
create primary xml index idx_xml_primary_book_ChapterDesc
on dbo.book(ChapterDesc)


/*=======================================================
2.建立辅助xml索引,下面的参数用于辅助索引,和xquery优化相关:

A.value辅助索引用于根据模糊路径创建索引。
B.path辅助索引根据路径和节点值创建索引。
C.property辅助索引根据某个路径查询节点值,来创建索引
========================================================*/
create xml index idx_xml_value_book_ChapterDesc
on dbo.book(ChapterDesc)
using xml index idx_xml_primary_book_ChapterDesc
for value


--3.查看xml索引元数据
select * from sys.xml_indexes

select *
from sys.indexes
where name in ('idx_xml_primary_book_ChapterDesc',
               'idx_xml_value_book_ChapterDesc')
  


在xml文档与关系型数据之间进行转换 

--1.把关系型数据格式化为xml
/*===============================================
<shifts>
  <shift OBJECT_ID="3" name="sysrscols" />
  <shift OBJECT_ID="5" name="sysrowsets" />
  <shift OBJECT_ID="7" name="sysallocunits" />
  <shift OBJECT_ID="8" name="sysfiles1" />
  <shift OBJECT_ID="17" name="syspriorities" />
  <shift OBJECT_ID="19" name="sysfgfrag" />
  <shift OBJECT_ID="23" name="sysphfg" />
  <shift OBJECT_ID="24" name="sysprufiles" />
</shifts>
=================================================*/
select top 8
       OBJECT_ID,      --属性
       name            --属性
from sys.objects
for xml raw('shift'),   --item
        root('shifts'), --根
        type


/*===============================================
<o object_id="37575172">
  <t name="wcObjects">
    <c name="name" />
    <c name="object_id" />
    <c name="principal_id" />
    <c name="schema_id" />
    <c name="parent_object_id" />
    <c name="type" />
    <c name="type_desc" />
    <c name="create_date" />
    <c name="modify_date" />
    <c name="is_ms_shipped" />
  </t>
</o>
=================================================*/
select top 10            --需要显示的列,所对应的表别名,作为item
                         --改变列的显示顺序会改变xml的层级
                         
       o.object_id,      --作为o的item中的object_id属性
       t.name,           --属性t的item中的name属性
       c.name            --属性作为c的item中的name属性
from sys.objects o
inner join sys.tables t
        on o.object_id = t.object_id
inner join sys.columns c
        on t.object_id = c.object_id
for xml auto,
        type



/*===============================================
<t object_id="37575172" name="wcObjects">
  <c name="name" />
  <c name="object_id" />
  <c name="principal_id" />
  <c name="schema_id" />
  <c name="parent_object_id" />
  <c name="type" />
  <c name="type_desc" />
  <c name="create_date" />
  <c name="modify_date" />
  <c name="is_ms_shipped" />
</t>
=================================================*/
select top 10            --需要显示的列,所对应的表别名,作为item
                         --改变列的显示顺序会改变xml的层级
                         
       t.object_id,      --作为t的item中的object_id属性
       t.name,           --属性t的item中的name属性,也就是说t有2个属性
       
       c.name            --属性作为c的item中的name属性
from sys.objects o
inner join sys.tables t
        on o.object_id = t.object_id
inner join sys.columns c
        on t.object_id = c.object_id
for xml auto,
        type



/*===============================================
<wc object_id="3" schema_id="4">
  <wc_name>sysrscols</wc_name>
</wc>
<wc object_id="5" schema_id="4">
  <wc_name>sysrowsets</wc_name>
</wc>
<wc object_id="7" schema_id="4">
  <wc_name>sysallocunits</wc_name>
</wc>
=================================================*/
select top 3
	   1 as tag,
	   null as parent,
	   object_id as [wc!1!object_id],
	   name as [wc!1!wc_name!element],
	   schema_id as [wc!1!schema_id]
from sys.objects o
for xml explicit,
        type
        


/*===============================================
<w>
  <wc wc_name="sysrscols" object_id="3">
    <schema_id>4</schema_id>
  </wc>
  <wc wc_name="sysrowsets" object_id="5">
    <schema_id>4</schema_id>
  </wc>
  <wc wc_name="sysallocunits" object_id="7">
    <schema_id>4</schema_id>
  </wc>
</w>
=================================================*/
select top 3
       name as '@wc_name',         --属性
       object_id as '@object_id',  --属性
       schema_id                   --item
from sys.objects o
for xml path('wc'),
        root('w'),
        type



--2.把xml转化为关系型
declare @book xml

set @book = 
	CAST('<book>
			  <chapters>
				   <chapter id="1">Installation,Upgrades</chapter>
			  </chapters>
			  <chapters>
				<chapter id="2">Configuring SQLServer</chapter>
			  </chapters>
	      </book>' as XML
	    )


--xml文档的句柄
declare @document int

--取得xml文档的句柄
exec sp_xml_preparedocument 
	@document output,
	@book
	
	
select chapter_id,
       chapter_name
       
from openxml(@document,
             '/book/chapters',
             1)
with (chapter_id int 'chapter/@id',
      chapter_name nvarchar(100) 'chapter')


--删除文档句柄指定的xml文档的内部表示形式,并使该文档句柄无效
exec sp_xml_removedocument @document


2、分层

 在SQL Server 2008中引入了hierarchyid数据类型,可以用来做本地存储,可以表示树层次结构中节点的位置,其中包含了几个可以操作、遍历层次结构的内置方法。

--1.建表,注意方法名称的大小写
create table dbo.webpage
	(webpageID hierarchyid not null,
	 positionDESC as webpageid.GetLevel(),  --取得层级
	 pageurl nvarchar(50) not null
	)


--插入数据
insert into dbo.webpage(webpageID,pageurl)
values('/','http://wc.com')

insert into dbo.webpage(webpageID,pageurl)
values('/1/','http://wc.com/abc/')

insert into dbo.webpage(webpageID,pageurl)
values('/2/','http://wc.com/wc.htm')

declare @parent hierarchyid
set @parent = CONVERT(hierarchyid,'/1/')

insert into dbo.webpage(webpageID,pageurl)
values(@parent.GetDescendant(null,null),
       'http://wc.com/abc/abc1.html')
       
insert into dbo.webpage(webpageID,pageurl)
values(@parent.GetDescendant(null,null),
       'http://wc.com/abc/abc2.html')
        


--2.显示层次数据
select webpageID,            --二进制表示
       webpageID.ToString(), --字符串表示
       positionDESC,
       pageurl
from dbo.webpage



--3.返回指定层级的向上指定级数的层级
select CONVERT(hierarchyid,'/1/1/').GetAncestor(1).ToString(),

       hierarchyid::Parse('/1/1/'),    --解析字符串转为hierarchyid
       
       hierarchyid::Parse('/1/1/').GetAncestor(1).ToString()

       

--4返回指定层级的子节点
select CONVERT(hierarchyid,'/1/').GetDescendant(null,null).ToString()


--5.返回节点的深度
sel
ect CONVERT(hierarchyid,'/1/1/1/1/').GetLevel()


--6.返回根节点
select hierarchyid::GetRoot()

select *
from dbo.webpage 
where webpageID = hierarchyid::GetRoot()


--7.验证是否是当前节点的子节点
select hierarchyid::Parse('/1/').IsDescendantOf('/')


--8.修改节点位置
select hierarchyid::Parse('/1/1/'),

       hierarchyid::Parse('/1/1/').GetReparentedValue('/1/',  --原来的上一级节点
                                                      '/2/')  --现在的上一级节点                                               


3、空间数据

SQL Server 2008引入了原生的空间数据存储,提供了geography和geometry两种新的数据类型,这些数据类型为位置和制图应用程序、几何形状的表示,提供了内建的功能。

geography数据类型可以存储圆球空间,也可以存储坐标的经度、纬度、点、多边形、曲线、集合。

geometry数据类型表示欧几里得坐标空间数据,也可以存储点、多边形、曲线、集合。SQL Server 2008支持文本(WKT)、二进制(WKB)、地理标记语言(GML)的XML格式,来表示矢量几何映射对象。开放地理空间联盟(OGC)中常用这些格式,这里通过WKT格式使用geography数据类型。

--1.空间数据
with Geo
as
(
select id,
       lon,
       lat,
       geography::Parse('POINT('+lon+space(1)+lat+')') as g       
from 
	(
		select 1 as id,'-16.96732' as lon,'36.943' as lat
		union all
		select 1,'-16.58963','36.943'
		       
	)a
where lon is not null and
      lat is not null
)


--2.计算坐标之间的距离
select 
       s.ID,
       g.STDistance(geography::Parse('POINT('+r.LON+SPACE(1)+r.LAT+')'))
from Geo s
inner join 
		(
			select 1 as id,'-116.26598' as lon,'39.27763' as lat
			union all
			select 1,'-16.32683','36.94673'
		) r
        on s.ID  = r.ID


--3.建立有空间数据的表
create table x
(
	v int not null identity(1,1) primary key,
	geog geography not null,
	geogWKT as geog.STAsText()
)


--4.添加空间数据
insert into x(geog)
values(geography::Parse('POLYGON(
                                  (-93.123 36.943,
                                   -93.126 36.953,
                                   -94.129 36.986,
                                   -93.123 36.943)
                                 )'
                       )
         ),   --多边形,开始坐标和结束坐标必须相同,注意polygon中必须包含2层括号,否则报错
       
       (geography::Parse('POINT(-93.123 36.943)')),    --点坐标
       
       (geography::Parse('LINESTRING(-93.123 36.943,
                                     -93.126 36.953)')
                         )  --两坐标之间的线


--5.地理数据的计算  
select v,
       geogWKT,
       geog.STDistance('POINT (-93.123 36.985)'),          --距离
       geog.STIntersects('POINT (-93.123 36.943)'),        --是否有交集
       geog.STLength(),                                    --长度
       geog.STArea(),                                      --多边形面积
       geog.STAsText()                                     --WKT格式的坐标      
from x


posted @ 2012-08-04 22:02  小木瓜瓜瓜  阅读(223)  评论(0编辑  收藏  举报