Oracle数据库中空间数据类型随着GIS、CAD/CAM的广泛应用,对数据库系统提出了更高的要求,不仅要存储大量空间几何数据,且以事物的空间关系作为查询或处理的主要内容。
Oracle数据库从9i开始对空间数据提供了较为完备的支持,增加了空间数据类型和相关的操作,以及提供了空间索引功能。
Oracle的空间数据库提供了一组关于如何存储,修改和查询空间数据集的SQL schema与函数。
通过MDSYS schema规定了所支持的地理数据类型的存储、语法和语义,提供了R-tree空间数据索引机制,定义了关于空间的相交查询、联合查询和其他分析操作的操作符、函数和过程,并提供了处理点,边和面的拓扑数据模型及表现网络的点线的网络数据模型。
Oracle中各种关于空间数据库功能主要是通过Spatial组件来实现。
从9i版本开始,Oracle Spatial空间数据库组件对存储和管理空间数据提供了较为完备的支持。
其主要通过元数据表、空间数据字段(即SDO_GEOMETRY字段)和空间索引来管理空间数据,并在此基础上提供一系列空间查询和空间分析的函数,让用户进行更深层次的GIS应用开发。
Oracle Spatial使用空间字段SDO_GEOMETRY存储空间数据,用元数据表来管理具有SDO_GEOMETRY字段的空间数据表,并采用R树索引和四叉树索引技术来提高空间查询和空间分析的速度。
1、元数据表说明。
Oracle Spatial的元数据表存储了有空间数据的数据表名称、空间字段名称、空间数据的坐标范围、坐标参考信息以及坐标维数说明等信息。
用户必须通过元数据表才能知道ORACLE数据库中是否有Oracle Spatial的空间数据信息。
一般可以通过元数据视图(USER_SDO_GEOM_METADATA)访问元数据表。
元数据视图的基本定义为:(TABLE_NAME V ARCHAR2(32),COLUMN_NAME V ARCHAR2(32),DIMINFO MDSYS.SDO_DIM_ARRAY,SRID NUMBER);其中,TABLE_NAME为含有空间数据字段的表名,COLUMN_NAME为空间数据表中的空间字段名称,DIMINFO是一个按照空间维顺序排列的SDO_DIM_ELEMENT对象的动态数组,SRID则用于标识与几何对象相关的空间坐标参考系。
SDO_DIM_ELEMENT对象的定义如下所示:Create Type SDO_DIM_ELEMENT as OBJECT (SDO_DIMNAME V ARCHAR2(64),SDO_LB NUMBER,SDO_UB NUMBER,SDO_TOLERANCE NUMBER);其中,SDO_DIMNAME是空间维名称,SDO_LB为该空间维的左下角坐标,SDO_UB为该空间维的右上角坐标,SDO_TOLERANCE为几何对象的表示精度。
2、空间字段说明Oracle Spatial的空间数据都存储在空间字段SDO_GEOMETRY中,理解SDO_GEOMETRY是编写Oracle Spatial接口程序的关键。
SDO_GEOMETRY是按照OpenGIS规范定义的一个对象,其原始的创建方式如下所示:CREATE TYPE sdo_geometry AS OBJECT (SDO_GTYPE NUMBER,SDO_SRID NUMBER,SDO_POINT SDO_POINT_TYPE,SDO_ELEM_INFO MDSYS.SDO_ELEM_INFO_ARRAY,SDO_ORDINATES MDSYS.SDO_ORDINATE_ARRAY);该对象由五个部分组成,下面分别介绍这五个部分的定义方法。
SDO_GTYPE是一个NUMBER型的数值,用来定义存储对象的类型。
SDO_SRID 也是一个NUMBER型的数值,它用于标识与几何对象相关的空间坐标参考系,Oracle Spatial规定,一个几何字段中的所有几何对象都必须为相同的SDO_SRID 值。
SDO_POINT是一个包含X,Y,Z数值信息的对象,用于表示几何类型为点的几何对象。
SDO_ELEM_INFO是一个可变长度的数组,每3个数作为一个元素单位,用于解释坐标是如何存储在SDO_ORDINATES数组中的。
SDO_ORDINATES是一个可变长度的数组,用于存储几何对象的真实坐标,该数组的类型为NUMBER型,它的最大长度为1048576。
SDO_ORDINATES必须与SDO_ELEM_INFO数组配合使用,才具有实际意义。
3、空间索引技术Oracle Spatial索引主要提供两个功能:找到一个区域中的空间对象,找到两个空间对象的交集。
为此,Spatial提供了R树索引和四叉树索引两种索引机制来提高空间查询和空间分析的速度。
R-Tree索引能代替线性四叉树索引或和其一起使用。
R-Tree索引不仅仅能对2D数据进行索引,同时对3D、4D数据也可进行索引。
空间R-tree索引最高能定位四维空间。
一个R-tree索引近似的使用单个MBR来代表一个地理对象。
它存储在空间索引表(USER_SDO_INDEX_METADATA视图中的SDO_INDEX_TABLE字段所指的空间索引表,如果你去查找那个字段内容,只会看到一堆二进制)。
同时R-tree 索引还维护一个sequence对象(USER_SDO_INDEX_METADATA表中的SDO_RTREE_SEQ_NAME字段)。
创建R树索引:CREATE INDEX territory_idx ON territories (territory_geom)INDEXTYPE IS MDSYS.SPATIAL_INDEX;创建四叉树索引:CREATE INDEX ROADS_FIXED ON ROADS(SHAPE) INDEXTYPE IS MDSYS.SPATIAL_INDEXPARAMETERS(‘SDO_LEVEL=8’);4、查询模型说明Oracle Spatial使用两层查询模型来解决查询与空间过滤的问题。
模型使用两个不同目的的操作来加快查询过程。
而输出的结果是这两个操作组合结果。
这两个操作为primary与secondary操作:1.primary过滤操作:使用地理上近似的查询操作来减小计算的复杂度。
因为这个查询是近似,所以它产生一个比较大的结果集,这个结果集是给secondary 过滤操作使用。
2.secondary过滤操作:在primary过滤出来的结果集上使用精确的计算来得到最后精度的空间过滤结果集。
因为这个计算过程是很昂贵的,所以它只在primary过滤出来的结果集上计算。
Spatial使用空间索引来实现primary过滤。
Spatial并不强求使用一定要使用primary与secondary过滤组合。
在很多情况下,光一个primary过滤就足够了。
例如一个放大操作中,应用程序只要得到与一个矩形框相交的地理区域中的内容。
这时,primary过滤就可以非常快的返回一个大集合,而应用程序可以使用减切路径来只显示出目标区域来。
Spataial使用secondary过滤器来决定空间关系。
空间关系决定于地理位置。
最通用的空间关系是基于拓扑与距离的。
为了决定空间关系,Spatail有很多secondary过滤器:SDO_RELATE操作指出拓扑关系。
它实现了九个交叠模型在点,线与多边形中间分类两个空间对象的拓扑关系,每个对象都有包含,交叠与不包含三种。
SDO_WITHIN_DISTANCE操作决定两个空间对象是否在某个指定的距离中。
SDO_NN操作指出离某个空间对象最近的对象。
SDO_WITHIN_DISTANCE操作符判断两个对象是否在一个指定的距离内,这个操作在B对象的周围建立一个为指定距离的区域,然后看A是否与这个区域相交。
SDO_NN操作返回在一个对象周围指定数目的最近对象。
下面一个在Oracle中构建空间数据库并对空间数据库进行增、删、改操作的实例。
通过这个实例可以看到Oracle中构建空间数据库功能强大,且实现十分简单。
首先建立一个城市表(用来表示彼此相连的城市)和关系表(用来表示城市之间的公路)。
Create table cities(Location mdsys.sdo_geometry // 城市位置Geom mdsys.sdo_geometry, // 城市边界City varchar2(42), // 城市名State_abrv varhar2(2), // 所属省份Pop number, // 人口数量Poppsqmi number); // 人口密度Create table interstates(Geom mdsys.sdo_geometry, // 城市间地形Highway varchar2(35)); // 高速路名接下来将限制条件插入到USER_SDO_GEOM_METADATA中:Insert into USER_SDO_GEOM_METADATA(table_name, colum_name, diminfo, srid)Values( ‘cities’, ‘location’,Mdsys.sdo_dim_array(mdsys.sdo_dim_element (‘x’, -180.000000000, 180.000000000, 0.000000050),mdsys.sdo_dim_element (‘y’, -90.000000000, 90000000000, 0.000000050),),Null);Insert into USER_SDO_GEOM_METADATA(table_name, colum_name, diminfo, srid)Values( ‘cities’, ‘geom’,Mdsys.sdo_dim_array(mdsys.sdo_dim_element (‘x’, -180.000000000, 180.000000000, 0.000000050),mdsys.sdo_dim_element (‘y’, -90.000000000, 90000000000, 0.000000050),),Null);Insert into USER_SDO_GEOM_METADATA(table_name, colum_name, diminfo, srid)Values( ‘interstates’, ‘geom’,Mdsys.sdo_dim_array(mdsys.sdo_dim_element (‘x’, -180.000000000, 180.000000000, 0.000000050),mdsys.sdo_dim_element (‘y’, -90.000000000, 90000000000, 0.000000050),),Null);现在需要为数据库建立索引:Create indes idx_intestates on interstates(geom)Indextype is mdsys.spatial_indexParameters(‘sdo_level = 9);以上是建立空间数据库的一些工作。