本单元将向您阐释如何使用 Oracle Locator 或 Oracle Spatial 以及 Oracle Workspace Manager 对当前数据和建议的数据进行基于位置的分析。
本单元将讨论以下主题:
| 概述 | ||
| 前提条件 | ||
| 加载新客户及其位置 | ||
| 在几何列上创建空间索引 | ||
| 执行基于位置的查询 | ||
| 使用 Workspace Manager 分析当前和建议的位置数据 | ||
将鼠标置于该图标上将显示所有屏幕截图。您也可以将鼠标置于每个图标上,只查看与之关联的屏幕截图。
Oracle Locator 和 Oracle Workspace Manager 均是 Oracle10i 数据库标准版和企业版的特性。Oracle Locator 提供了一组集成的功能和过程,可以使用标准 SQL 在 Oracle 数据库中高效地存储、管理、查询和分析空间数据。Oracle Workspace Manager 允许您在同一数据库中对当前数据、建议的数据以及历史数据进行管理。
Oracle Spatial 是 Oracle10i 数据库企业版的一个选件,它是 Oracle Locator 的补充,可以提供更多高端空间功能,包括:环域生成、空间聚合、面积计算等功能;线性参照;坐标系转换;拓扑数据模型;以及对地理参照栅格数据的支持。
MyCompany 拥有几个主要仓库。它需要找到靠近给定仓库的客户,告知他们新的促销信息。为了确定客户的位置并执行基于位置的分析,MyCompany 必须存储仓库和客户的位置数据。
本教程使用 customers 和 warehouses 表,这些表位于 OE 模式中。
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_language | VARCHAR2(3) |
| nls_territory | VARCHAR2(30) |
| credit_limit | NUMBER(9.2) |
| cust_email | VARCHAR2(30) |
| 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 的数据类型包括:
| 数字 (NUMBER) | |
|
字符 (VARCHAR2) |
|
| 日期 (DATE) | |
| 空间数据 (MDSYS.SDO_GEOMETRY)。可以将位置存储为表的 SDO_GEOMETRY 列中的一个点。客户的位置与地球表面的经度值和纬度值相关联,例如,-63.13631,52.485426。 |
在开始本单元的学习之前,您应当已经完成了以下步骤:
| 1. | ||
| 2. | ||
| 3. |
将 spatial.zip 下载到工作目录中。 |
|
在本部分中,假设您已经加载了 Order Entry (OE) 模式,该模式包含 customers 和 warehouses 表。执行下列任务:
| 1. | 加载位置数据 |
| 2. | 将新客户及其位置添加到 customers 表 |
| 3. | 将元数据添加到 user_sdo_geom_metadata 视图 |
Order Entry 模式中的几个客户和仓库的位置值均为 NULL。要为这些客户和仓库提供位置,请执行以下步骤:
| 1. |
从工作目录 /home/oracle/wkdir 打开一个 SQL*Plus 会话,执行以下命令: sqlplus oe/oe@<sid> @loc_updates |
|
使用事务插入将新客户及其位置添加到 customers 表。可以将客户的位置存储为表的 SDO_GEOMETRY 列中的一个点。客户的位置与地球表面的经度值和纬度值相关联(例如,-63.136,52.4854)。Oracle Locator 和 Oracle Spatial 要求您将经度值置于纬度值之前。在下面的 INSERT 语句中,将使用 SDO_GEOMETRY 构造函数插入点位置。
要将新客户及其位置添加到 customers 表,请执行以下步骤:
| 1. |
从 SQL*Plus 会话登录到 OE 模式,运行 @insert_customers.sql。 |
|
以下是本练习中要填充的 SDO_GEOMETRY 构造函数的简要说明:
MDSYS.SDO_GEOMETRY (2001,8307,
MDSYS.SDO_POINT_TYPE(-63.13631,52.485424,NULL),NULL,NULL)
该语法中各元素的含义分别如下:
在创建空间索引之前,必须将 customers 和 warehouses 表的元数据添加到 USER_SDO_GEOM_METADATA 视图。
| 为每个 SDO_GEOMETRY 列添加一行 | |
| customers 的 SDO_GEOMETRY 列为 cust_geo_location。 | |
| warehouses 的 SDO_GEOMETRY 列为 wh_geo_location。 |
要为客户和仓库添加元数据,请执行以下步骤:
| 1. |
从登录到 OE 模式的 SQL*Plus 会话中,运行 @add_metadata.sql。 |
|
以下是所插入信息的说明:
| 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.sql 创建索引。 |
|
| LAYER_GTYPE | 该参数既充当约束又充当优化程序的提示。如果使用参数 LAYER_GTYPE =POINT,则进行检查以确保所有几何对象都是点,还要检查参数以确保对点数据进行优化处理。customers 和 warehouses 都只包含点几何对象。 |
在随后的页面中,您将学习如何执行以下类型的基于位置的查询:
| 1. | 使用空间索引查找距离某仓库最近的五个邻居,无附加约束 |
| 2. | 使用空间索引在某个位置上查找五个距离最近的邻居,有附加约束 |
| 3. | 使用空间索引标识距另一位置指定距离的位置集 |
执行以下步骤:
| 1. |
从登录到 OE 模式的 SQL*Plus 会话中,运行 @query1.sql: |
|
以下是对 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 只考虑近似值。例如,如果您希望找出位于纽约的五个最近客户,而其中四个客户位于新泽西,因而将某个 |
要返回 5 个最近客户的实际距离,您可以使用 SDO_NN_DISTANCE 操作符。执行以下步骤:
| 1. |
从登录到 OE 模式的 SQL*Plus 会话中,运行 @query2.sql: |
|
以下是对 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 子句可确保按顺序返回距离 — 最短的距离位于最前面。 |
执行以下步骤:
| 1. |
从登录到 OE 模式的 SQL*Plus 会话中,运行 @query3.sql: |
|
以下是对 select 参数的说明:
| SDO_BATCH_SIZE 是一个可调整的参数,它可以影响查询的性能。SDO_NN 同时在内部计算距离的数值。最初返回的一批行可能无法满足 WHERE 子句中的约束,因此继续返回由 SDO_BATCH_SIZE 指定的行数,直至满足 WHERE 子句中的所有约束。您应当选择一个 SDO_BATCH_SIZE,以使最初返回的行数满足 WHERE 子句中的约束。 | |
| SDO_NN 操作符中使用的 UNIT 参数指定了 SDO_NN_DISTANCE 参数的度量单位。默认单位是与数据相关联的度量单位。对于经度和纬度数据,默认单位是米。 | |
| c.cust_address.state_province = 'NY' 和 rownum < 6 是 WHERE 子句中的附加约束。rownum < 6 子句对于将返回的结果数限制为少于 6 必不可少。 | |
| ORDER BY DISTANCE_IN_MILES 子句可确保按顺序返回距离,最短的距离位于最前面,其度量单位是英里。 |
执行以下步骤:
| 1. |
从登录到 OE 模式的 SQL*Plus 会话中,运行 @query4.sql: |
|
以下是对 select 参数的说明:
| SDO_WITHIN_DISTANCE 操作符从 customers 表返回距离仓库 3 一百英里以内的客户。SDO_WITHIN_DISTANCE 的第一个参数(上例中的 c.cust_geo_location)是要搜索的列。SDO_WITHIN_DISTANCE 的第二个参数(上例中的 w.wh_geo_location)是要确定距离远近的位置。不应该对返回结果的顺序进行假设。例如,返回的第一行并不保证就是距离仓库 3 最近的客户。 | |
| SDO_WITHIN_DISTANCE 操作符中使用的 DISTANCE 参数指定距离值;在本例中,该值为 100。 | |
| SDO_WITHIN_DISTANCE 操作符中的 UNIT 参数指定 DISTANCE 参数的度量单位。默认单位是与数据相关联的度量单位。对于经度和纬度数据而言,默认单位是米;在本例中为英里。 |
执行以下步骤:
| 1. |
从登录到 OE 模式的 SQL*Plus 会话中,运行 @query5.sql: |
|
以下是对 select 参数的说明:
| SDO_GEOM.SDO_DISTANCE 函数计算客户所处位置与仓库 3 之间的精确距离。SDO_GEOM.SDO_DISTANCE 的第一个参数(上例中的 c.cust_geo_location)包含了要计算与仓库 3 之间距离的客户所处的位置。SDO_WITHIN_DISTANCE 的第二个参数(上例中的 w.wh_geo_location)是仓库 3 的位置,函数将要计算其与客户所处位置之间的距离。 | |
| SDO_GEOM.SDO_DISTANCE 的第三个参数 (0.005) 是公差值。该公差值是由 Oracle Spatial 使用的舍入误差值。对于经度和纬度数据,该公差值以米为单位。在本例中,该公差值为 5 mm。 | |
| SDO_GEOM.SDO_DISTANCE 参数中使用的 UNIT 参数指定由 SDO_GEOM.SDO_DISTANCE 函数所计算距离的度量单位。默认单位是与数据相关联的度量单位。对于经度和纬度数据,默认单位是米。在本例中,单位是英里。 | |
| ORDER BY DISTANCE_IN_MILES 子句可确保按顺序返回距离,最短的距离位于最前面,其度量单位是英里。 |
基于函数的索引使得可以基于返回 SDO_GEOMETRY 对象的函数结果构建索引。这种强大的机制可以实现基于位置的功能,而无需表中具有 SDO_GEOMETRY 列。基于函数的索引主要用于具有存储经度和纬度数据的列的表上。
要创建并使用基于函数的索引,执行以下步骤:
| 1. | |
| 2. | |
| 3. | 创建基于函数的空间索引 |
| 4. | 使用基于函数的空间索引 |
在继续之前,必须运行 wh_updates.sql 脚本。该脚本会将 wh_longitude 和 wh_latitude 列添加到 warehouses 表。wh_longitude 和 wh_latitude 都是 NUMBER 类型的列,我们将使用基于函数的索引按空间对它们进行索引。
| 1. |
从登录到 OE 模式的 SQL*Plus 会话中,运行 @wh_updates.sql 以加载数据。 |
|
要创建返回 SDO_GEOMETRY 对象的函数,执行以下步骤:
| 1. |
在创建函数之前,需要确保 OE 具有进行此项工作的权限。同时,授予 OE 权限,允许 Oracle 优化程序使用基于函数的索引。指定以下命令: connect system/<password>@<sid>; grant create procedure to oe; Grant query rewrite to oe; |
|
| 2. |
同样,以 oe/oe 连接实例。 |
|
| 3. |
从登录到 OE 模式的 SQL*Plus 会话中,运行 @create_function.sql: |
|
必须将该函数声明为 DETERMINISTIC,否则优化程序可能无法使用最优的计划。对于返回对象的函数来说都是如此。GET_GEOM 函数接受两个 NUMBER 类型的参数,返回一个 MDSYS.SDO_GEOMETRY 对象
在创建空间索引前,必须将元数据添加到 user_sdo_geom_metadata 视图。为返回 SDO_GEOMETRY 对象的函数增加了一行。
要将元数据添加到返回 SDO_GEOMETRY 对象的函数,执行以下步骤:
| 1. |
从登录到 OE 模式的 SQL*Plus 会话中,运行 @add_metadata_fi.sql: |
|
将 GET_GEOM 函数加载到 user_sdo_geom_metadata 的 COLUMN_NAME 列中。将函数的所有者 (OE) 包含在函数调用中。GET_GEOM 函数的参数(wh_longitude、wh_latitude)是 warehouses 表中的经度列和纬度列。
要创建基于函数的索引,用户必须具有查询重写权限。因为您已经将这些权限授予了 OE 用户,所以可以继续该步骤来创建索引。要创建基于函数的索引,执行以下步骤:
| 1. |
从登录到 OE 模式的 SQL*Plus 会话中,运行 @create_function_index.sql: |
|
GET_GEOM 函数以 CREATE_INDEX 语句的 COLUMN_NAME 参数的形式调用。GET_GEOM 函数的参数(wh_longitude、wh_latitude)是 warehouses 表中的经度列和纬度列。
执行以下步骤:
| 1. |
要使用基于函数的索引执行查询,需要具有会话权限。必须针对该会话将 QUERY_REWRITE_ENABLED 设为 True,将 QUERY_REWRITE_INTEGRITY 设为 Trusted。现在返回查询 3。但是,此时应根据 SDO_NN 操作符的第二个参数而不是 SDO_GEOMETRY 列使用基于函数的空间查询。 |
|
| 2. |
从登录到 OE 模式的 SQL*Plus 会话中,运行 @query3_wfi.sql。结果如下: |
|
GET_GEOM 函数以 SDO_NN 操作符的第二个参数的形式调用。GET_GEOM 函数的参数(wh_longitude、wh_latitude)是 warehouses 表中的经度列和纬度列。
MyCompany 计划再建造一个仓库,从而为客户提供更好的服务。目前有两个地点可供选择。MyCompany 希望使用 SQL 应用程序来对这些候选地点进行分析。为此,必须将两个候选地点的数据输入生产仓库表。然而,将候选地点数据隔离以使其不会影响到非地点选择小组成员员工的工作,这一点非常重要。隔离候选地点数据还将使两个地点选择小组能够同时展开工作。
Oracle Workspace Manager 能够将当前行、建议行以及历史行保存在同一个表中。它不要求更改应用程序 SQL (DML)。通过允许生产用户访问当前数据,同时其他用户进入工作区以创建并访问建议数据值和历史数据值,员工之间的协同工作性得以提升。工作区中进行的更改可以合并至当前数据中形成一个整体。Workspace Manager 使用户能够在工作区中做出更改的情况下对数据库有一个全面的了解。通过它,开发人员不用再编写自定义代码,DBA 也不用再复制和同步多个数据库副本或添加应用程序特定的元数据来跟踪行版本了。
在本部分中,您将执行以下任务:
| 1. | |
| 2. | |
| 3. | |
| 4. |
当表支持版本控制时,表中的所有行都可支持多个版本的数据。版本控制的行作为原始行存储在同一表格中。工作区是一种虚拟环境,由一个或多个用户共享来对数据库中的数据进行更改。在该数据库中有一个工作区层次结构。默认情况下,在创建工作区时,从最上层始终称为“LIVE”的数据库工作区进行创建。
首先,使仓库表支持版本控制,并在 LIVE 之外创建两个工作区(SITE1 和 SITE2),每个选择小组使用一个。

执行以下步骤:
| 1. |
从登录到 OE 模式的 SQL*Plus 会话中,运行 @init_workspaces.sql。 |
|
用户须进入工作区才能对数据进行更改。工作区按逻辑将一个或多个支持版本控制的表中的行版本集合进行分组,并在将其显式地合并至生产数据前隔离这些版本。
转至工作区 SITE1 并添加第一个建议的仓库位置。转至工作区 SITE2,添加第二个建议的仓库位置,其属性与 SITE1 的相同,只是位置不同。转至工作区 LIVE 和“select all from wrehouse”表,候选地点没有显示。SITE1 中的用户无法看到 SITE2 中所做的更改,反之亦然。执行以下步骤:
| 1. |
从登录到 OE 模式的 SQL*Plus 会话中,运行 @add_workspace_data.sql。 |
|
数据库用户不会看到版本控制基础架构,并且执行选择、插入、修改以及删除数据等操作的应用程序 SQL 数据处理语句 (DML) 继续在支持版本控制的表中正常运行。工作区中的用户可自动查看感兴趣的正确版本的记录,即用户无需跟踪版本链并指定所感兴趣的版本。
依次进入每个工作区并使用现有的应用程序 SQL 执行基于位置的查询,以报告每个地点在 100 英里以内具多少个客户。最终结果是,在 100 英里内,SITE1 有 3 个客户,而 SITE2 有 25 个客户。执行以下步骤:
| 1. |
从登录到 OE 模式的 SQL*Plus 会话中,运行 @goto_workspace_and_query.sql。 向下滚动查看其余数据。 |
|
工作区可以被合并、刷新或回滚。合并工作区需要将子工作区中所做的更改应用到其父工作区。刷新工作区需要将父工作区中的更改应用到子工作区。回滚工作区需要删除工作区中所做的更改。用户可以删除所有自工作区创建以来所做的更改,或只删除保存点之后的更改。如果某行在子工作区和父工作区中均进行了更改,则会导致数据冲突。冲突可随时得到检查和解决。请求合并或刷新操作时,会自动检测冲突。
因为 SITE2 在 100 英里以内有更多的客户,所以将其合并至工作区 LIVE 以使所有用户都可访问 SITE2 的数据。转至工作区 LIVE 和“select all from wrehouse”表,SITE2 的数据已显示在其中。回滚不需要的 SITE1 数据将其删除,删除该工作区并禁用该工作区表上的版本控制。执行以下步骤:
| 1. |
从登录到 OE 模式的 SQL*Plus 会话中,运行 @merge_workspace_cleanup.sql。 |
|