Oracle 空间数据库基础(基于11g)

本文档详细介绍了Oracle Spatial 11g的基础知识,包括数据导入、空间元数据理解、sdo_geometry数据类型及其应用。通过实例演示了如何使用sql语句操作Geometry数据,以及道格拉斯-普克算法简化线和缓冲区生成等空间分析操作。
摘要由CSDN通过智能技术生成

Oracle Spatial基础(基于11g)

本过程来源于上学期课程《空间数据库》课余设计,Oracle对空间数据的支持使得其在GIS方向有其独有的优势,由于近期有用到Oracle的需求,故重新整理了一下之前的文档以备用及分享,如有错误请留言指出。

教材基于Oracle11g,网上关于Oracle的资源教程较少且多基于此版本,所以笔者推荐11g用于熟悉工作。

转载请注明来源。

文章目录

一、数据导入

1.前期准备:

  • Oracleg11g:部署基本环境(https://blog.csdn.net/m0_37768631/article/details/89164329);

  • sqlplus、sqlDeveloper:用于管理及操作空间数据库、管理及操作数据,后者为图形化操作界面;本组主要进行几何形状展示,未涉及属性,否则需借助Mapbuilder或Geoserver.

  • Mapbuilder:用于显示携带空间信息数据表,可用于代码测试及结果展示;更方便地可通过sqldeveloper或PLSQL地图视图查看几何信息并编辑,可在oracle官网下载对应版本;

  • 教材参考——《Oracle Spatial空间信息管理:Oracle Database 11g-清华大学出版社》,十分经典实用的教材。

    • 链接:https://pan.baidu.com/s/1dDKd6yVjQT6BzW__gXeLEQ ,提取码:s3n4
    • 内容有侵权请联系删除
  • 关于Oracle Spatial自带的一些函数可用看这个参考及教程,文末我使用其中的缓冲区及道格拉斯函数进行了简单的示例,可自行参考

2.测试数据导入

2.1 教材参考数据导入(from .dmp格式)

我首先通过系统账号SYS/SYSTEM创建了新账户Spatial(且我设置我的密码为spatial)并授予管理权限,因为如果使用系统账户登录,其自带大量表格不便于查询及管理。具体查看电子书前言部分

  • 通过SqlPlus导入(cmd中输入):–imp **账号/**密码@数据库实例 dmp所在文件地址 其他参数(可选)

  • Imp数据文件地址:官方提供:https://github.com/Apress/pro-oracle-spatial-for-oracle-db-11g

    • ①、imp spatial/spatial@orcl

      file= C:\Users\admin\Desktop\Coding\Oracle\Examples\Data\app_data.dmp ignore=y FULL=y;

    • ②、imp spatial/spatial@orcl

      file= C:\Users\admin\Desktop\Coding\Oracle\Examples\Data\citybldgs.dmp ignore=y FULL=y;

    • ③、imp spatial/spatial@orcl

      file= C:\Users\admin\Desktop\Coding\Oracle\Examples\Data\gc.dmp ignore=y FULL=y;

    • ④、imp spatial/spatial@orcl

      file= C:\Users\admin\Desktop\Coding\Oracle\Examples\Data\map_detailed.dmp ignore=y FULL=y;

    • ⑤、imp spatial/spatial@orcl

      file= C:\Users\admin\Desktop\Coding\Oracle\Examples\Data\map_large.dmp ignore=y FULL=y;

    • ⑥、imp spatial/spatial@orcl

      file= C:\Users\admin\Desktop\Coding\Oracle\Examples\Data\net.dmp ignore=y FULL=y;

    • ⑦、imp spatial/spatial@orcl

      file= C:\Users\admin\Desktop\Coding\Oracle\Examples\Data\routing.dmp ignore=y FULL=y;

    • ⑧、imp spatial/spatial@orcl

      file= C:\Users\admin\Desktop\Coding\Oracle\Examples\Data\styles.dmp ignore=y FULL=y;

    • ⑨、imp spatial/spatial@orcl

      file= C:\Users\admin\Desktop\Coding\Oracle\Examples\Data\zip.dmp ignore=y FULL=y;

/* 函数说明:CCENSE/CCENSE@OracleDB —>用户名/密码@数据库实例

​ file=“本地路径+需要导入/导出的dmp文件全称”

​ log=“日志文件”

​ FULL=y;

注意:此语句应该在CMD中运行

*/

  • 教材提供数据齐全,包含美国地区点、线、面数据及部分全球数据表,部分表含人口等统计数据可用。
2.2 通过shapefile文件导入

此处导入有很多种方式,最简单易行的是通过mapbuild工具直接导入

  • 打开mapbuild并连接数据库
    在这里插入图片描述
  • tools——import shapefile
    在这里插入图片描述

二、了解空间元数据

1.什么是元数据

狭隘的说,可以理解为对二元表的某一字段(列)的约束格式,如我需要限制某表日期这一列为年月日格式且日期处在1998年1月1日之后,就是其“元数据”

  • 携带空间信息的表通常将其几何对象存储在SDO_GEOMETRY列中,这是专用于存储空间数据的数据类型,下章会介绍;这一列数据的所有对象即作为一个空间层

  • 所以:要对该列几何对象进行操作(验证、建索引、查询等)需只指定元数据

  • 包含信息,该信息以字典形式存储在:其他用户→MDSYS→视图→user_sdo_geometry_metadata中,可自行查看,如下

    • 维数

    • 维度的边界

    • 容差

    • 坐标系

在这里插入图片描述

2.字典视图说明

  • table_name 和 column_name用于唯一标识每个空间层
  • diminfo用于存储维度信息
  • srid此属性很重要,用于存储坐标系的相关信息
2.1 diminfo属性说明

在这里插入图片描述

!也就是说若该列为点——经纬度坐标,则会有两个element类型,一个经度一个维度

  • sdo_dim_array说明
    在这里插入图片描述

    • 一个名称、一个大小范围、一个容差,容差一般默认,主要影响涉及要素距离的查询精度
2.2 srid属性说明
  • 该字段一般用数字代码指定坐标系,见示例
    在这里插入图片描述

3. 示例——填充空间元数据

  • 此表为customers Table

INSERT INTO USER_SDO_GEOM_METADATA VALUES
(
'CUSTOMERS', 表名
'LOCATION', 指定列名
SDO_DIM_ARRAY -- DIMINFO attribute for storing dimension bounds, tolerance存储维度信息的属性字段
	(							//两个ELEMENT,说明为(x,y)形式
		 SDO_DIM_ELEMENT		//这是第一个元素
		 (
		 'LONGITUDE', -- DIMENSION NAME for first dimension
		 -180, -- SDO_LB for the dimension
		 180, -- SDO_UB for the dimension
		 0.5 -- Tolerance of 0.5 meters		//指定名称、上下限和容差,下同
		 ),
		 SDO_DIM_ELEMENT		//这是第二个
		 (
		 'LATITUDE', 
		 -90, 
		 90, 
		 0.5 
		 )
	),
8307 -- SRID代表大地坐标系
);

三、*sdo_geometry数据类型

1.可存储哪些几何数据?

  • 可以存储点线面及其集合
  • 针对不同的几何体不展开描述,本身也不难理解
  • 我们更加关心的是如何实现?——不难想到,用数组

在这里插入图片描述

2.geometry的逻辑实现

在这里插入图片描述

  • 下图为几何类型的构造图及关系,对于我们而言应该很眼熟(在AE开发中常用)

  • 简单来讲就是一个坐标的标准+N个坐标,如我建立一个笛卡尔坐标系,然后用数组存储即可如:[(x1,y1,z1), (x2,y2, z2), (x3, y3, z3),...]

    对于更复杂的形体则通过如下列关系层层包含嵌套存储:

在这里插入图片描述

3.geometry的类型、属性和值的描述

在这里插入图片描述

3.1 gtype——维度和形状的确定

在这里插入图片描述
在这里插入图片描述

3.2 srid——坐标系的确定
  • *这部分要展开内容会很丰富,但实际中不需要深究、有需要可看教材详解
3.3 sdo_point——确定单点坐标

很容易理解,就是存储 ( X , Y , Z   ) ( X,Y,Z\ ) (X,Y,Z 坐标对,其数据类型的描述如下

在这里插入图片描述

  • 以下示例为插入一个点到已知表中

    INSERT INTO geometry_examples (name, description, geom) VALUES
    (
    'POINT',
    '2-dimensional Point at coordinates (-79,37) with srid set to 8307',
    SDO_GEOMETRY
    (
    2001, -- SDO_GTYPE format: D00T. Set to 2001 for a 2-dimensional point
    8307, -- SDO_SRID (geodetic)
    SDO_POINT_TYPE
    (
    -79, -- ordinate value for Longitude
    37, -- ordinate value Latitude
    NULL -- no third dimension (only 2 dimensions)
    ),
    NULL,
    NULL
    )
    );//五个元素的填充,点、后两个默认为空

在这里插入图片描述

  • 另外,我们可以通过更为通俗易懂的方式(使用构造函数)构造一个点,如下

在这里插入图片描述

在这里插入图片描述

3.4 element_info和ordinates——线、面(多点)及复杂几何体

这里简单描述:

  • ordinates为一系列的坐标点,应数组存储如:

在这里插入图片描述

  • element_info用于指定这些点如何组成几何体
  • 示例:见下一节

四、空间数据的加载

  • 往SDO_GEOMETRY列中插入数据,以面数据为例,代码可自行在资料中获取

在这里插入图片描述

在这里插入图片描述

五、sql语句操作Geometry数据——举例

1.读取几何信息

  • 以下代码(来自数据)展示创建一个新的店铺(分店)位置,计算店铺能销售客户的区域范围,并创建一个运输的路径,且当货车运行时对线路进行延伸

DECLARE
b_long NUMBER;
b_lat NUMBER;
new_long NUMBER;
new_lat NUMBER;
new_branch_loc SDO_GEOMETRY;
sales_region SDO_GEOMETRY;
route SDO_GEOMETRY;
//变量声明
BEGIN
-- Obtain Old location for branch id=1
SELECT br.location.sdo_point.x, br.location.sdo_point.y
INTO b_long, b_lat
FROM branches br
WHERE id=1;
//将获取的x,y赋值给经纬度变量
-- Compute new coordinates: say the location is displaced by 0.0025 degrees
new_long := b_long+ 0.0025;
new_lat := b_lat + 0.0025;
//生成新的点——作为新点的位置
-- Create new branch location using old location
new_branch_loc :=
point
(
X=> new_long,
Y=> new_lat,
SRID=> 8307
) ;
//用上述获取的新点创建新分店
-- Compute sales region for this branch
sales_region :=
rectangle
(
CTR_X=> new_long,
CTR_Y=> new_lat,
EXP_X=> 0.005,
EXP_Y=> 0.0025,
SRID=> 8307
) ;
//计算销售区域(范围)
-- Create Delivery Route
route :=
line
(
FIRST_X=> -122.4804,
FIRST_Y=> 37.7805222,
NEXT_X=> -123,
NEXT_Y=> 38,
SRID=> 8307
) ;
//创建运输路线
-- Update Delivery Route by adding new point
route :=
add_to_line
(
GEOM=> route,
POINT => POINT(-124, 39, 8307)
) ;
//通过加点调整运输路线
-- Perform additional analysis such as length of route,
-- or # of customers in sales region (we will see examples in Chapters 8 and 9)
-- ...
-- Update geometry in branches table
UPDATE branches SET LOCATION = new_branch_loc WHERE id=1;
//刷新
END;

2.oracle数组(array)基础

  • 相比于常规的语言sql数字操作显得较为麻烦,需要输血

  • array是可以嵌套使用的,并且其内部有序

  • 先通过一个较为综合的示例进行讲解,后续展开

    SET SERVEROUTPUT ON
    DECLARE

    -- Declare a type for the VARRAT
    TYPE MY_ARRAY_TYPE IS VARRAY(10) OF NUMBER;
    //声明一个自定义的数组的类型
    -- Declare a varray variable
    V MY_ARRAY_TYPE;
    //定义一个数组V
    -- Other variables
    I NUMBER;
    K NUMBER;
    L NUMBER;
    ARRAY_CAPACITY NUMBER;
    N_ENTRIES NUMBER;
    //其他变量定义
    BEGIN
    -- Initialize the array
    V := MY_ARRAY_TYPE (1,2,3,4);
    //数组初始化
    -- Get the value of a specific entry
    DBMS_OUTPUT.PUT_LINE('* Values for specific array entries');
    K := V(3);
    DBMS_OUTPUT.PUT_LINE('V(3)='|| V(3));
    I := 2;
    L := V(I+1);
    DBMS_OUTPUT.PUT_LINE('I=' || I);
    DBMS_OUTPUT.PUT_LINE('V(I+1)=' || V(I+1));
    //下表访问取值,输出打印

    -- Find the capacity of a VARRAY:
    DBMS_OUTPUT.PUT_LINE('* Array capacity');
    ARRAY_CAPACITY := V.LIMIT();
    DBMS_OUTPUT.PUT_LINE('Array Capacity: V.LIMIT()='||V.LIMIT());
    N_ENTRIES := V.COUNT();
    DBMS_OUTPUT.PUT_LINE('Current Array Size: V.COUNT()='||V.COUNT());
    //打印(输出)当前数组的容量

    -- Range over all values in a VARRAY
    DBMS_OUTPUT.PUT_LINE('* Array Content');
    FOR I IN 1..V.COUNT() LOOP
    DBMS_OUTPUT.PUT_LINE('V('||I||')=' || V(I));
    END LOOP;
    //使用for循环遍历数组中的值

    FOR I IN V.FIRST()..V.LAST() LOOP
    DBMS_OUTPUT.PUT_LINE('V('||I||')=' || V(I));
    END LOOP;
    //first()和last()分别返回array[]最小和最大的下标

    I := V.COUNT();
    WHILE I IS NOT NULL LOOP
    DBMS_OUTPUT.PUT_LINE('V('||I||')=' || V(I));
    I := V.PRIOR(I);
    END LOOP;
    //prior(x)和next(x)返回前一个和后一个下标,如上用来后向遍历

    -- Extend the VARRAY
    DBMS_OUTPUT.PUT_LINE('* Extend the array');
    I := V.LAST();
    V.EXTEND(2);
    V(I+1) := 5;
    V(I+2) := 6;
    //给数组append值

    DBMS_OUTPUT.PUT_LINE('Array Capacity: V.LIMIT()='||V.LIMIT());
    DBMS_OUTPUT.PUT_LINE('Current Array Size: V.COUNT()='||V.COUNT());
    FOR I IN 1..V.COUNT() LOOP
    DBMS_OUTPUT.PUT_LINE('V('||I||')='|| V(I));
    END LOOP;

    -- Shrink the VARRAY
    DBMS_OUTPUT.PUT_LINE('* Trim the array');
    V.TRIM();
    //弹出trim()
    DBMS_OUTPUT.PUT_LINE('Array Capacity: V.LIMIT()='||V.LIMIT());
    DBMS_OUTPUT.PUT_LINE('Current Array Size: V.COUNT()='||V.COUNT());
    FOR I IN 1..V.COUNT() LOOP
    DBMS_OUTPUT.PUT_LINE('V('||I||')='|| V(I));
    END LOOP;

    -- Delete all entries from the VARRAY
    DBMS_OU

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值