2009年5月8日星期五

oracle spatial 进行基于位置的分析 来自oracle的官方教程

http://www.oracle.com/technology/global/cn/obe/10gr2_db_single/datamgmt/spatial/spatial_otn.htm?
执行基于位置的分析 

目的 

本教程介绍了如何对当前和建议的数据进行基于位置的分析。 

所需时间 

大约 45 分钟。 

主题 

本教程包括下列主题: 

概述 
情景 
前提条件 
加载新客户及其位置 

在几何列上创建空间索引 

执行基于位置的查询 
创建并使用基于函数的索引 

使用 Workspace Manager 分析当前和建议的位置数据 

总结 
查看屏幕截图 

将鼠标置于此图标上以加载和查看本教程的所有屏幕截图。(警告:因为此操作会同时加载所有屏幕截图,所以网速较慢时,响应时间可能会比较长。) 

注意:此外,您还可以在下列步骤中将鼠标放在每个单独的图标上,从而仅加载和查看与该步骤相关的屏幕截图。可以通过单击各个屏幕截图来将其隐藏。 

概述 

Oracle Locator 和 Oracle Workspace Manager 是 Oracle 数据库 10g 标准版和企业版的功能。Oracle Locator 提供了一组集成的功能和过程,可以使用标准 SQL 在 Oracle 数据库中高效地存储、管理、查询和分析空间数据。Oracle Workspace Manager 允许您在同一数据库中对当前数据、建议的数据以及历史数据进行管理。 

Oracle Spatial 是 Oracle 数据库 10g 企业版的一个选件,它是 Oracle Locator 的补充,可以提供更多高端空间功能,包括:缓冲区生成、空间聚合、面积计算等功能;线性参照;坐标系转换;拓扑数据模型;以及对地理参照栅格数据的支持。 

返回主题列表 

案例 

MyCompany 拥有几个主要仓库。它需要找到靠近给定仓库的客户,告知他们新的促销息。为了确定客户的位置并执行基于位置的分析,MyCompany 必须存储仓库和客户的位置数据。 

本教程将使用 OE 模式中的 CUSTOMERS 和 WAREHOUSES 表。 

CUSTOMERS 表具有以下字段: 

列 数据类型 
CUSTOMER_ID NUMBER(6) 
CUST_FIRST_NAME VARCHAR2(20) 
CUST_LAST_NAME VARCHAR2(20) 
CUST_ADDRESS CUST_ADDRESS_TYP 
PHONE_NUMBERS PHONE_LIST_TYP 
NLS_LANGAUGE VARCHAR2(3) 
NLS_TERRITORY VARCHAR2(30) 
CREDIT_LIMIT NUMBER(9.2) 
CUST_EMAIL VARCHAR2(20) 
ACCOUNT_MGR_ID NUMBER(6) 
CUST_GEO_LOCATION MDSYS.SDO_GEOMETRY 
WAREHOUSES 表具有以下字段: 

列 数据类型 
WAREHOUSE_ID NUMBER(3) 
WAREHOUSE_SPEC SYS.XMLTYPE 
WAREHOUSE_NAME VARCHAR2(35) 
LOCATION_ID NUMBER(4) 
WH_GEO_LOCATION MDSYS.SDO_GEOMETRY 
Oracle 数据类型 

Oracle 数据类型包括: 

数字 (NUMBER) 
字符 (VARCHAR2) 
日期 (DATE) 
空间数据 (MDSYS.SDO_GEOMETRY)。可以将位置存储为表的 SDO_GEOMETRY 列中的一个点。客户的位置与地球表面的经度值和纬度值相关联,例如,-63.13631,52.485426。 
返回主题列表 

前提条件 

开始本教程之前,您应该: 

1.
完成了教程在 Windows 上安装 Oracle 数据库 10g。 

2.
下载 spatial.zip 文件并将其解压缩到您的工作目录 (c:\wkdir) 中。 

返回主题列表 

加载新客户及其位置 

在本教程中,假设您已经加载了 Order Entry (OE) 模式 — 该模式包含 CUSTOMERS 和 WAREHOUSES 表。执行下列任务: 

加载位置数据 
将新客户及其位置添加到 CUSTOMERS 表 
将元数据添加到 USER_SDO_GEOM_METADATA 视图 
返回主题列表 

加载位置数据 

Order Entry 模式中的几个客户和仓库的位置值均为 NULL。要为这些客户和仓库提供位置,执行以下命令: 

cd \wkdir 
sqlplus oe/oe 
@loc_updates 


返回主题 

将新客户及其位置添加到 CUSTOMERS 表 

使用事务插入将新客户及其位置添加到 CUSTOMERS 表。可以将客户的位置存储为表的 SDO_GEOMETRY 列中的一个点。客户的位置与地球表面的经度值和纬度值相关联(例如,-63.136,52.4854)。Oracle Locator 和 Oracle Spatial 要求您将经度值置于纬度值之前。在下面的 INSERT 语句中,将使用 SDO_GEOMETRY 构造函数插入点位置。 

要将新客户及其位置添加到 CUSTOMERS 表,执行以下步骤: 

1. 

在登录 OE 模式的 SQL*Plus 会话中,运行以下脚本: 

@insert_customers 
该脚本包含以下语句: 

REM script name: insert_customers.sql 
REM Inserts values for CUSTOMERS table in the OE schema 

REM 
REM CUSTOMERS 
REM 


DELETE FROM customers WHERE 
           customer_id = 1001; 


INSERT INTO customers VALUES 
   (1001,'Dennis','Green', 
   cust_address_typ('1 Oracle Drive','03062','Nashua','NH','US'), 
   PHONE_LIST_TYP('+1 603 897 4104'), 
   'us','AMERICA','100','Dennis.Green@Oracle.com', 
   149, 
   MDSYS.SDO_GEOMETRY(2001, 8307, 
   MDSYS.SDO_POINT_TYPE (-63.13631, 52.485424,NULL),NULL,NULL), 
   '01-JAN-60','married', 'M', '110,000 - 129,999'); 
        
DELETE FROM customers WHERE 
           customer_id = 1002; 
           
INSERT INTO customers VALUES 
   (1002,'John','Smith', 
   cust_address_typ('1910 Oracle Way','20190','Reston','VA','US'), 
   PHONE_LIST_TYP('+1 703 364 4111'), 
   'us','AMERICA','100','John.Smith@Oracle.com', 
   149, 
   MDSYS.SDO_GEOMETRY(2001, 8307, 
   MDSYS.SDO_POINT_TYPE(-70.120133, 44.795766,NULL),NULL,NULL), 
   '02-MAY-70', 'single', 'M', '70,000 - 89,999'); 


commit; 




SDO_GEOMETRY 构造函数说明 

以下是本练习中要填充的 SDO_GEOMETRY 构造函数的简要说明: 

MDSYS.SDO_GEOMETRY (2001,8307, 
MDSYS.SDO_POINT_TYPE(-63.13631,52.485424,NULL),NULL,NULL) 

该语法中各元素的含义分别如下: 

2001 这是 SDO_GTYPE 属性,在存储二维单点(如客户位置)时将其设为 2001。 
8307 这是空间参照系 ID (SRID):Oracle 词典表 (MDSYS.CS_SRS) 的外键,它包含了所有受支持的坐标系。将客户的位置与坐标系相关联至关重要。本例中,8307 对应于“经度/纬度 (WGS 84)”。 
MDSYS.SDO_POINT_TYPE 这是在 SDO_GEOMETRY 构造函数内存储经度值和纬度值的地方。请注意,您还可以存储第三个值,但是对于这些教程而言,所有客户数据都是二维的。 
NULL, NULL 最后两个空值超出了本教程的讨论范围。无需了解 SDO_GEOMETRY 构造函数的最后两个字段,您就可以构造基于位置的强大查询了。有关 SDO_GEOMETRY 对象中所有字段的详细信息,请参考 Oracle Spatial 用户指南和参考。现在,应将最后这两个字段都设为 NULL。 
返回主题 

将元数据添加到 USER_SDO_GEOM_METADATA 视图 

在创建空间索引前,必须将 CUSTOMERS 和 WARESHOUSES 表的元数据添加到 USER_SDO_GEOM_METADATA 视图。 

注意: 

为每个 SDO_GEOMETRY 列添加一行 
CUSTOMERS 的 SDO_GEOMETRY 列是 cust_geo_location。 
WAREHOUSES 的 SDO_GEOMETRY 列是 wh_geo_location。 
要为客户和仓库添加元数据,执行以下步骤: 

1. 

在登录 OE 模式的 SQL*Plus 会话中,运行以下脚本: 

@add_metadata 

该脚本包含以下语句: 

REM 
REM USER_SDO_GEOM_METADATA, CUSTOMERS and WAREHOUSES 
REM 
-- inserting data into the user_sdo_geom_metadata view 
DELETE FROM USER_SDO_GEOM_METADATA 
   WHERE TABLE_NAME = 'WAREHOUSES' AND COLUMN_NAME = 'WH_GEO_LOCATION' ; 
INSERT INTO USER_SDO_GEOM_METADATA (TABLE_NAME, COLUMN_NAME, DIMINFO, SRID) 
   VALUES ('WAREHOUSES', 'WH_GEO_LOCATION', 
   MDSYS.SDO_DIM_ARRAY 
   (MDSYS.SDO_DIM_ELEMENT('LONG', -180.0, 180.0, 0.005), 
   MDSYS.SDO_DIM_ELEMENT('LAT', -90.0, 90.0, 0.005) 
   ), 
   8307); 
   COMMIT; 
DELETE FROM USER_SDO_GEOM_METADATA 
   WHERE TABLE_NAME = 'CUSTOMERS' AND COLUMN_NAME = 'CUST_GEO_LOCATION' ; 
INSERT INTO USER_SDO_GEOM_METADATA (TABLE_NAME, COLUMN_NAME, DIMINFO, SRID) 
   VALUES ('CUSTOMERS', 'CUST_GEO_LOCATION', 
   MDSYS.SDO_DIM_ARRAY 
   (MDSYS.SDO_DIM_ELEMENT('LONG', -180.0, 180.0, 0.005), 
   MDSYS.SDO_DIM_ELEMENT('LAT', -90.0, 90.0, 0.005) 
   ), 
   8307); 

COMMIT; 


以下是所插入信息的说明: 

TABLE_NAME 这是包含空间数据的表的名称。 
COLUMN_NAME 这是存储空间数据的 SDO_GEOMETRY 列的名称。 
MDSYS.SDO_DIM_ARRAY 这是保存 MDSYS.SDO_DIM_ELEMENT 对象的构造函数,该函数依次将空间数据的范围存储在每个维中 (-180.0, 180.0),公差值为 (0.005)。这个公差是 Oracle Spatial 使用的舍入误差值,经度和纬度数据以米为单位。在本例中,该公差值为 5 mm。 
8307 这是空间参照系 id (SRID):Oracle 典表 (MDSYS.CS_SRS) 的外键,它包含了所有受支持的坐标系。将客户的位置与坐标系相关联至关重要。本例中,8307 对应于“经度/纬度 (WGS 84)”。 
返回主题 

在几何列上创建空间索引 

现在,可以为 CUSTOMERS 和 WAREHOUSES 创建空间索引了: 

1. 

在登录 OE 模式的 SQL*Plus 会话中,运行以下脚本: 

@create_indexes 

该脚本包含以下语句: 

-- creating spatial indexes 
-- **NOTE** storage parameters should be modified for large tables 
-- if the tablespace is not locally managed. 
DROP INDEX warehouses_sidx; 
CREATE INDEX warehouses_sidx ON warehouses(WH_GEO_LOCATION) 
           indextype is mdsys.spatial_index; 
DROP INDEX customers_sidx; 
CREATE INDEX customers_sidx ON customers(CUST_GEO_LOCATION) 
           indextype is mdsys.spatial_index; 






LAYER_GTYPE 该参数既充当约束又充当优化程序的提示。如果使用参数 LAYER_GTYPE =POINT,则进行检查以确保所有几何对象都是点,还要检查参数以确保对点数据进行优化处理。customers 和 warehouses 都只包含点几何对象。 
返回主题列表 

执行基于位置的查询 

您将了解如何执行以下类型的基于位置的查询: 

使用空间索引查找距离某仓库最近的五个邻居(无附加约束) 
使用空间索引在某个位置上查找五个距离最近的邻居(有附加约束) 
使用空间索引标识距另一位置指定距的位置集 
返回主题列表 

使用空间索引查找距离某仓库最近的五个邻居(无附加约束) 

查询 1:查找距离 ID 为 2 的仓库最近的五个客户。 

执行以下步骤: 

1. 

在登录 OE 模式的 SQL*Plus 会话中,运行以下脚本: 

@query1 
该脚本包含以下语句: 

-- Finds the 5 closest customers to warehouse_id = 2 
SELECT /*+ordered*/ 
   c.customer_id, 
   c.cust_first_name, 
   c.cust_last_name 
FROM warehouses w, 
   customers c 
WHERE w.warehouse_id = 2 
AND sdo_nn (c.cust_geo_location, w.wh_geo_location, 'sdo_num_res=5') = 'TRUE'; 




以下是对 select 参数的说明: 

/*+ordered*/ 提示是优化程序的提示,它可确保首先搜索 WAREHOUSES 表。 
SDO_NN 操作符从 CUSTOMERS 表返回距离仓库 2 最近的客户的 SDO_NUM_RES 值。SDO_NN 的第一个参数(上例中的 c.cust_geo_location)是要搜索的列。SDO_NN 的第二个参数(上例中的 w.wh_geo_location)是所要查找最近邻居的位置。不应该对返回结果的顺序进行假设。例如,返回的第一行不能确保是距离仓库 2 最近的客户。如果两个或多个客户距离仓库的距离相等,则可能在对 SDO_NN 的后续调用中返回其中一个。 
在使用 SDO_NUM_RES 参数时,WHERE 子句中没有使用其他约束。SDO_NUM_RES 只考虑近似值。例如,如果您希望找出位于纽约的五个最近客户,而其中四个客户位于新泽西,因而将某个条件添加到 WHERE 子句,那么上述查询将返回一行。该行为特定于 SDO_NUM_RES 参数,而其结果可能不是您想要的。在查询 3 中,您将了解到如何查找位于纽约的 5 个最近的客户。 
查询 2:查找距离仓库 2 最近的 5 个客户,并按距离顺序显示结果 

要返回 5 个最近客户的实际距离,您可以使用 SDO_NN_DISTANCE 操作符。执行以下步骤: 

1. 

在登录 OE 模式的 SQL*Plus 会话中,运行以下脚本: 

@query2 
该脚本包含以下语句: 

-- Finds the 5 closest customers to warehouse_id = 2 
-- and orders the results by distance 
SELECT /*+ordered*/ 
   c.customer_id, 
   c.cust_first_name, 
   c.cust_last_name, 
   sdo_nn_distance (1) distance 
FROM warehouses w, 
   customers c 
WHERE w.warehouse_id = 2 
AND sdo_nn 
(c.cust_geo_location, w.wh_geo_location, 'sdo_num_res=5', 1) = 'TRUE' 
ORDER BY distance; 




以下是对 select 参数的说明: 

SDO_NN_DISTANCE 操作符是 SDO_NN 操作符的辅助操作符;它只能在 SDO_NN 操作符内使用。该操作符的参数是一个与被指定为 SDO_NN 最后一个参数的数字相匹配的数字;在本例中为 1。这个参数没有隐含意义,它只是一个标记。如果指定了 SDO_NN_DISTANCE(),则可以按距离对结果进行排序,并确保返回的第一行是距离仓库最近的客户。如果要查询的数据是以经度和纬度形式存储的,则 SDO_NN_DISTANCE 的默认单位是米。 
SDO_NN 操作符还带有 UNIT 参数,它决定 SDO_NN_DISTANCE 返回的度量单位。但本例中并不使用该参数。 
ORDER BY DISTANCE 子句可确保按顺序返回距离 — 最短的距离位于最前面。 
返回主题 

使用空间索引在某个位置上查找五个距离最近的邻居(有附加约束) 

查询 3:查找 5 个居住在纽约州且距离仓库 3 最近的客户,并以英里为单位按距离顺序返回结果 

执行以下步骤: 

1. 

在登录 OE 模式的 SQL*Plus 会话中,运行以下脚本: 

@query3 
该脚本包含以下语句: 

REM Finds the 5 closest customers to warehouse_id = 3 
REM who reside in NY state, and return the distance in miles, 
REM and order the results by distance 
REM 
REM CUSTOMERS and WAREHOUSES 
REM 


set lines 132 
set pages 1000 


SELECT /*+ordered*/ 
   c.customer_id, 
   c.cust_address.state_province state, 
   sdo_nn_distance(1) distance_in_miles 
FROM warehouses w, 
   customers c 
WHERE w.warehouse_id = 3 
AND sdo_nn (c.cust_geo_location, w.wh_geo_location, 
   'sdo_batch_size =5 unit=mile', 1) = 'TRUE' 
AND c.cust_address.state_province = 'NY' 
AND rownum < state_province =" 'NY'" warehouse_id="3 " warehouse_id =" 3 " warehouse_id =" 3 " distance =" 100" unit="MILE')" warehouse_id =" 3 " unit="MILE')" warehouse_id =" 3 " distance =" 100" unit="MILE')" wh_longitude =" -103.00195," wh_latitude =" 36.500374 " warehouse_id =" 1; " wh_longitude =" -124.21014," wh_latitude =" 41.998016 " warehouse_id =" 2; " wh_longitude =" -74.695305," wh_latitude =" 41.35733 " warehouse_id =" 3; " wh_longitude =" -123.61526," wh_latitude =" 46.257458 " warehouse_id =" 4; " wh_longitude =" -79.4167," wh_latitude =" 43.6667 " warehouse_id =" 5; " wh_longitude =" 151.2000," wh_latitude =" -33.8833 " warehouse_id =" 6; " wh_longitude =" -106.0500," wh_latitude =" 24.3833 " warehouse_id =" 7; " wh_longitude =" 123.8839," wh_latitude =" 39.8667 " warehouse_id =" 8; " wh_longitude =" 72.8333," wh_latitude =" 18.9667 " warehouse_id =" 9; " table_name =" 'WAREHOUSES' " column_name =" 'OE.GET_GEOM(WH_LONGITUDE,WH_LATITUDE)'" layer_gtype="point" initial="1K" next="1K" pctincrease="0'); " warehouse_id =" 3 " query_rewrite_enabled =" TRUE; " query_rewrite_integrity =" TRUSTED; " warehouse_id =" 3 " sdo_batch_size ="5" unit="mile'," state_province =" 'NY' " warehouse_id =" 10" warehouse_id="10" unit="MILE')" warehouse_id =" 10" distance =" 100" unit="MILE')" unit="MILE')" warehouse_id =" 10" distance =" 100" unit="MILE')" remove_workspace="">TRUE) ; 

SELECT warehouse_id, warehouse_name, location_id 
FROM warehouses 
WHERE warehouse_id=10 ; 

exec dbms_wm.DisableVersioning('warehouses') ; 
exec dbms_wm.DisableVersioning('inventories') ; 

ALTER TABLE Warehouses 
MODIFY (wh_longitude null, wh_latitude null); 




返回主题 

总结 

在本教程中,您学习了如何: 

加载新客户及其位置 

在几何列上创建空间索引 

执行基于位置的查询 
创建并使用基于函数的索引 

使用 Workspace Manager 分析当前和建议的位置数据 

没有评论: