MySQL基础14 — 空间数据类型

概述

本章,您将学习 MySQL 中的空间数据类型。

如同 Redis 的 geospatial 数据类型一样(geospatial 是一种使用经纬度标识地理位置的数据类型),MySQL 也有类似存储地理位置信息的数据类型,被称为空间数据类型。

术语说明

  • 地理特征:指地球上任何具有明确位置的事物,可分为以下三类:

    • 实体 - 自然实体(山脉、湖泊等)与人造实体(城市、道路等)
    • 空间 - 例如通过行政区域划分的城镇、通过气候带划分的热带等
    • 可定义位置 - 能够通过特定参照系或描述方式明确标识的空间点位。例如可以通过经纬度来描述地标建筑的位置;以当前道路为参照物,该地标建筑位于道路西北方向的 1 KM 位置处。
  • 几何(Geometry):表示世界上任何具有地理位置的事物所对应的‌点或点的集合‌。地理要素(geographic feature)、地理空间要素(geospatial feature)、要素(feature)或几何(geometry)都是同义词,其中最常用的术语是‌几何。几何的本意为 "对地球的测量",另一层含义源于测绘学,指制图师用于绘制世界的几何特征。

  • OGC(Open Geospatial Consortium):开放地理空间联盟是一个由250多家企业、机构和高校组成的国际性联盟,其主要作用之一是制定开放标准(如 WMS、WFS、WCS等),作用之二是通过成员协作(包括政府、企业、学术机构)解决空间信息集成问题‌。OGC 标准是地理信息系统(GIS)开发的基础规范‌,除此之外,卫星调度、Web 地图服务等场景均依赖 OGC 标准实现数据交换‌。有关 OGC 的内容,请参阅 这里这里

  • OpenGIS:OGC 制定的一套服务框架的技术统称,关键组成包括:

    • 数据模型(如 ‌SRS‌)
    • 服务接口(如 ‌WMS、WFS、WCS‌)
    • 编码格式(如 GML、KML)
  • SRS(Spatial Reference System,空间参考系统):OpenGIS 的核心基础组件(如地基一般的重要性),用来描述空间数据的坐标系统和测量基准。在 OpenGIS 中规定:

    • 所有空间数据必须绑定一个 SRS 标识(SRID
    • 空间计算(如距离/面积)必须基于 SRS 定义的坐标规则执行
  • 笛卡尔 SRS(Cartesian SRS):指一个没有指定地理坐标系的平面坐标系,常用于局部坐标系或假设的平面地图,如建筑平面图设计、仓库货架定位系统、电路板元件布局、游戏地图坐标

  • 地理 SRS:使用经纬度坐标表示地球表面位置的地理坐标系,常用于城市级地图应用、全球物流跟踪、地理信息系统(GIS)、任何涉及地球曲率的应用

Q:什么是 SRID?

用来唯一标识 SRS 的一种数值编码,其类似于现实世界中各个国家的邮政编码(每个国家的邮政编码规则都不同),不同 SRID 对应不同的坐标系统定义,确保空间数据的准确解析与转换,常有:

  • 4326 - 经纬度
  • 3857 - 网页地图
  • 4490 - 中国北斗导航系统

所有的 SRID 可通过 该网站 进行查询。

提示
EPSG 是国际石油与天然气生产者协会(IOGP)下属的权威组织,负责维护全球坐标参考系统的标准数据集,包括椭球体、投影参数等元数据‌。EPSG 为 SRID 提供权威编码规则,在 OGC 标准中,SRID 通常与 EPSG 代码相对应,比如 SRID 4326 等同于 EPSG:4326。
  • 几何对象:MySQL 在处理空间数据时,需要使用相关的函数(如 ST_GeomFromText( ) 函数)将 WKT 或 WKB 格式的字符串转换为数据库可识别的几何类型。

  • 质心(Centroid):几何学中的一个重要概念,也称为几何中心或重心。对于均匀材质的物体,质心就是质量的中心点。

空间数据类型

GEOMETRY 是所有空间几何类型的超类(Superclass),可以表示任何几何形状(点、线、面、集合体等),其子类(或称派生类)包括:

  • POINT - 用来表示一个点的坐标,常用来存储经纬度坐标。有关经纬度的知识,请参阅 前面 Redis 的书写内容。
  • LINESTRING - 表示由多个点连接而成的线
  • POLYGON - 表示一个多边形,其由多个点组成的闭区间
  • MULTIPOINT - 多个点的集合
  • MULTILINESTRING - 多条线的集合
  • MULTIPOLYGON - 表示多个多边形的集合
  • GEOMETRYCOLLECTION - 表示多种几何形状的集合(如同时包含点、线、面)。

空间数据类型的格式

两种标准空间数据格式:

  1. WKT(Well-Known Text)格式 - 以 ASCII 格式交换几何数据
  2. WKB(Well-Known Binary)格式 - 以二进制流形式交换几何数据

WKT 格式

  1. 对于 POINT

    POINT(15 20)

    横坐标在前,纵坐标在后,横坐标与纵坐标使用空格分隔(而不是用逗号)。若定义了 SRID,则 15 表示纬度,20 表示经度。

  2. 对于 LINESTRING

    LINESTRING(0 0, 10 10, 20 25, 50 60)

    这是由四个点连接而成的线,每个点使用逗号进行分隔。

  3. 对于 POLYGON

    POLYGON((0 0,10 0,10 10,0 10,0 0),(5 5,7 5,7 7,5 7, 5 5))

    在这个示例中,我们表示了一个包含两个环的多边形:

    • 外环多边形 - 由坐标点(0 0)→(10 0)→(10 10)→(0 10)→(0 0)构成的矩形
    • 内环多边形 - 由坐标点(5 5)→(7 5)→(7 7)→(5 7)→(5 5)构成的小矩形
  4. 对于 MULTIPOINT

    MULTIPOINT(0 0, 20 20, 60 60)
  5. 对于 MULTILINESTRING

    MULTILINESTRING((10 10, 20 20), (15 15, 30 15))
  6. 对于 MULTIPOLYGON

    MULTIPOLYGON(((0 0,10 0,10 10,0 10,0 0)),((5 5,7 5,7 7,5 7, 5 5)))
  7. 对于 GEOMETRYCOLLECTION

    GEOMETRYCOLLECTION(POINT(10 10), POINT(30 30), LINESTRING(15 15, 20 20))

    由两个 POINT 和一个 LINESTRING 组成的几何集合

可使用下面的函数将 WKB 格式转换为 WKT 格式:

SELECT ST_AsText(ST_GeomFromWKB(wkb_data));

WKB 格式

该格式通常需要使用特定函数进行转换,例如将 POINT 转换为几何对象,然后将几何对象转换为 WKB 格式:

SELECT ST_AsBinary(ST_GeomFromText('POINT(15 20)'));

格式对比

WKB WKT
优点 直接内存操作,性能提升 40% 以上;更加节省存储空间,适合大数据量和高频操作;避免了文本转换时的精度损失 可读性强,便于调试与修改;纯文本特性便于传输以及跨系统交换
缺点 人类不可读且难以调试 占用空间比 WKB 大 30%~50%;需要对文本进行解析,处理速度较慢
适用场景 高精度专业领域,如测绘、科学计算等 一般性质的常规应用

创建空间列

使用 create table 语法在创建表时创建空间列(这里没有显式定义 SRID):

create table if not exists geom(
    g geometry
);
提示
在实际的生产环境下,通常都需要显式定义 SRID,这对于 InnoDB 存储引擎在处理空间数据时会带来极大的好处(在一致性、兼容性以及性能等方面)。
    create table if not exists geom1(
        g1 geometry srid 4326
    );

在表已经存在的情况下使用 alter table ... add ... 语法添加空间列:

alter table geom add pt POINT;

使用 alter table ... drop ... 语法删除表的空间列:

alter table geom drop pt;

填充空间列

我们需要在 insert into 语句中使用特定的函数将几何对象进行插入(注意!直接使用 WKB 或 WKT 格式的字符串进行填充会报错)。有关空间函数的内容,后面会介绍。

众所周知,MySQL 中的变量分为系统变量、用户变量以及特殊的局部变量。系统变量有全局级(global,影响所有的会话)和会话级(session,仅影响当前连接的会话),查询与修改变量值时,系统变量需要用到 @@;用户变量只能作用于当前的连接会话,查询与赋值时需要用到 @,断开连接后释放变量;局部变量用在 begin...end 代码块中,必须通过 DECLARE 关键字进行显式声明,然后用 set 关键字进行赋值。

# 在插入数据之前执行转换
set @gdata1:=ST_GeomFromText('point(15 20)');

insert into geom values(@gdata1);

# 查询数据
select ST_AsText(g) as `a` FROM geom;
a
POINT(15 20)

# 也可以不断改变该变量的值然后插入数据
set @gdata1:=ST_GeomFromText('LINESTRING(0 0,1 1,2 2)');
insert into geom values(@gdata1);

set @gdata1:=ST_GeomFromText('POLYGON((0 0,10 0,10 10,0 10,0 0),(5 5,7 5,7 7,5 7, 5 5))');
insert into geom values(@gdata1);

set @gdata1:=ST_GeomFromText('GEOMETRYCOLLECTION(POINT(1 1),LINESTRING(0 0,1 1,2 2,3 3,4 4))');
insert into geom values(@gdata1);

# 查询的数据
select ST_AsText(g) as `b` FROM geom;
b
POINT(15 20)
LINESTRING(0 0,1 1,2 2)
POLYGON((0 0,10 0,10 10,0 10,0 0),(5 5,7 5,7 7,5 7,5 5))
GEOMETRYCOLLECTION(POINT(1 1),LINESTRING(0 0,1 1,2 2,3 3,4 4))
  • ST_GeomFromText( ) 函数表示将 WKT 格式的字符串转换为数据库可识别的几何对象。
  • ST_AsText( ) 函数表示将几何对象转换为 WKT 格式

获取空间数据

获取 WKT 格式的空间数据:

select ST_AsText(g) from geom;

获取 WKB 格式的空间数据:

select ST_AsBinary(g) from geom;

优化空间数据

与常规数据类型使用 B-Tree/B+ Tree 数据结构提高查询效率类似,MySQL 对空间列的 SPATIAL 索引采用基于二次分割(quadratic splitting)的 R-Tree 结构实现,相关的创建语法如下:

# 在创建表时创建空间列的 SPATIAL 索引
create table if not exists 表名(
    空间列名 空间数据类型关键字 not null srid 4326,
    spatial index(空间列名)
);

# 在表已经存在空间列的情况下创建 SPATIAL 索引
alter table 表名 add spatial index(空间列名);

使用 SPATIAL 索引请注意以下几点:

  • SPATIAL 索引仅适用于 InnoDB 和 MyISAM 存储引擎的表
  • SPATIAL 索引仅针对单个空间列
  • 相应的空间列 必须not null 约束
  • 不能 应用于有主键约束或唯一约束的列

使用下面的语法查询表中的 SPATIAL 索引:

show index from 表名;

若要删除表中的 SPATIAL 索引,请使用下面的语法:

alter table 表名 drop index 空间列名;

以上面创建的 geom 表为例来演示 SPATIAL 索引:

# 为已经存在的空间列添加 not null 约束
alter table geom modify g geometry not null;

# 应用 SPATIAL 索引
alter table geom add spatial index(g);

# 查看 SPATIAL 索引
## 在输出信息中,index_type 列的值为 SPATIAL
show index from geom;

# 删除表中的 SPATIAL 索引
alter table geom drop index g;

# 再次查阅,无输出信息
show index from geom;

有关索引所涵盖的知识,后面会有专门的文档进行说明

空间函数

所有的空间函数请参阅此链接——https://dev.mysql.com/doc/refman/8.4/en/spatial-function-reference.html

根据不同的功能,可划分为:

  • 一般几何属性函数
  • 点几何属性相关函数
  • 线几何属性相关函数
  • 面几何属性相关函数
  • 空间关系相关函数
  • 几何计算函数
  • 辅助函数

一般几何属性函数

  • ST_Dimension( ) 函数:返回几何对象的拓扑维度,语法为 ST_Dimension(g),参数 g 表示必选的几何对象(通过 ST_GeomFromText( ) 函数生成),其返回值可以是

    • -1 - 空几何
    • 0 - 没有长度与面积的几何
    • 1 - 长度非零且面积为零的几何
    • 2 - 非零面积的几何

    在 OpenGIS 中规定,POINTMULTIPOINT 的维度为 0,LINESTRINGMULTILINETRING 的维度为 1,POLYGONMULTIPOLYGON 的维度为 2

    select ST_Dimension(ST_GeomFromText('linestring(1 1,2 2)')) AS a;
    +------+
    | a    |
    +------+
    |    1 |
    +------+
    1 row in set (0.00 sec)
  • ST_GeometryType( ) 函数:返回几何对象的标准 OGC 名称,用法为 ST_GeometryType(g)

    # 这里只是示例,因为我已经提前输入了 POLYGON 空间数据
    select ST_GeometryType(ST_GeomFromText('POLYGON((0 0,10 0,10 10,0 10,0 0),(5 5,7 5,7 7,5 7,5 5))')) as b;
    +---------+
    | b       |
    +---------+
    | POLYGON |
    +---------+
    1 row in set (0.00 sec)
  • ST_IsEmpty( ) 函数:判断几何对象是否为空,为空,返回 1,不为空,返回 0

    正确示例:

    select ST_IsEmpty(ST_GeomFromText('GEOMETRYCOLLECTION empty')) as c;
    +------+
    | c    |
    +------+
    |    1 |
    +------+
    1 row in set (0.00 sec)
    
    select ST_IsEmpty(ST_GeomFromText('POINT(10 15)')) as c;
    +------+
    | c    |
    +------+
    |    0 |
    +------+
    1 row in set (0.00 sec)

    错误示例:

    # 语法错误,MySQL 不支持 POINT EMPTY
    select ST_IsEmpty(ST_GeomFromText('POINT EMPTY'));
    ERROR 3037 (22023): Invalid GIS data provided to function st_geomfromtext.
    
    # 不能直接向函数传递 WKB 或 WKT 格式的字符串
    select ST_IsEmpty('point(10 15)');
    ERROR 3037 (22023): Invalid GIS data provided to function st_isempty.

点几何属性相关函数

对于笛卡尔 SRS,则可以使用以下函数

  • ST_X( ) 函数 - 提取点几何的横坐标,用法为 ST_X(p),p 表示 POINT 几何对象

    select ST_X(ST_GeomFromText('point(100 200)')) as x;
    +------+
    | x    |
    +------+
    |  100 |
    +------+
    1 row in set (0.05 sec)
  • ST_y( ) 函数 - 提取点几何的纵坐标,用法为 ST_Y(p)

对于地理 SRS,则可以使用以下函数:

  • ST_Latitude( ) 函数 - 提取点几何的经度,用法为 ST_Latitude(p)

    select ST_Latitude(ST_GeomFromText('POINT(45 90)', 4326)) as a;
    +------+
    | a    |
    +------+
    |   45 |
    +------+
    1 row in set (0.00 sec)
  • ST_Longitude( ) 函数 - 提取点几何的纬度,用法为 ST_Longitude(p)

线几何属性相关函数

函数参数中的 ls 表示 LINESTRING 几何对象,部分函数也支持 MULTILINESTRING 几何对象

  • ST_StartPoint( ) 函数 - 返回线的起始点,用法为 ST_StartPoint(ls)

  • ST_EndPoint( ) 函数 - 返回线的最后一个点,用法为 ST_EndPoint(ls)

    select ST_AsText( ST_EndPoint(ST_GeomFromText('LINESTRING(0 0, 10 10, 20 25, 50 60)')) ) as a;
    +--------------+
    | a            |
    +--------------+
    | POINT(50 60) |
    +--------------+
    1 row in set (0.03 sec)
  • ST_IsClosed( ) 函数 - 判断 LineString 是否闭合(闭合指的是线的起始点相同)。若闭合则返回 1 ,若未闭合则返回 0

    set @ls1:='LINESTRING(1 1,2 2,3 3,2 2)';
    set @ls2:='LineString(1 1,2 2,3 3,1 1)';
    
    select ST_IsClosed(ST_GeomFromText(@ls1));
    +------------------------------------+
    | ST_IsClosed(ST_GeomFromText(@ls1)) |
    +------------------------------------+
    |                                  0 |
    +------------------------------------+
    1 row in set (0.02 sec)
    
    select ST_IsClosed(ST_GeomFromText(@ls2));
    +------------------------------------+
    | ST_IsClosed(ST_GeomFromText(@ls2)) |
    +------------------------------------+
    |                                  1 |
    +------------------------------------+
    1 row in set (0.00 sec)
  • ST_Length( ) 函数 - 计算 LineString 或 MultiLineString 的总长度,用法为 ST_Length(ls [, unit])

    • 如果几何对象是笛卡尔 SRS (Cartesian SRS)中的有效 LineString,则返回值是几何体的笛卡尔长度
    • 如果几何对象是笛卡尔 SRS 中的有效 MultiLineString,则返回值是其元素的笛卡尔长度之和
    • 如果几何对象是地理 SRS(geographic SRS) 中的有效 LineString,则返回值是该 SRS 中几何对象的大地测量长度,单位为米(metre)
    • 如果几何对象是地理 SRS 中的有效 MultiLineString,则返回值是该 SRS 中其元素的大地测量长度之和,单位为米(metre)
    • 未指定 unit 单位,笛卡尔 SRS 和地理 SRS 都已米为单位。支持的单位在 information_schema.ST_UNITS_OF_MEASURE 表中有记录
    select * from information_schema.st_units_of_measure where unit_name='metre';
    +-----------+-----------+-------------------+-------------+
    | UNIT_NAME | UNIT_TYPE | CONVERSION_FACTOR | DESCRIPTION |
    +-----------+-----------+-------------------+-------------+
    | metre     | LINEAR    |                 1 |             |
    +-----------+-----------+-------------------+-------------+
    1 row in set (0.00 sec)
    # 笛卡尔 SRS 示例
    set @ls:=ST_GeomFromText('LineString(1 1,2 2,3 3)');
    select ST_Length(@ls);
    +--------------------+
    | ST_Length(@ls)     |
    +--------------------+
    | 2.8284271247461903 |
    +--------------------+
    1 row in set (0.06 sec)
    
    SET @mls:=ST_GeomFromText('MultiLineString((1 1,2 2,3 3),(4 4,5 5))');
    SELECT ST_Length(@mls);
    +-------------------+
    | ST_Length(@mls)   |
    +-------------------+
    | 4.242640687119286 |
    +-------------------+
    1 row in set (0.00 sec)
    
    # 地理 SRS 示例,使用英尺单位
    set @ls:=ST_GeomFromText('LineString(1 1,2 2,3 3)', 4326);
    select ST_Length(@ls,'foot');
    +-----------------------+
    | ST_Length(@ls,'foot') |
    +-----------------------+
    |    1029205.9131247795 |
    +-----------------------+
    1 row in set (0.00 sec)
  • ST_NumPoints( ) 函数 - 显示 LineString 中 Point 的数量,用法为 ST_NumPoints(ls)

    set @num:=ST_GeomFromText('LineString(1 1,5 5, 10 10 ,1 1)');
    select ST_NumPoints(@num);
    +--------------------+
    | ST_NumPoints(@num) |
    +--------------------+
    |                  4 |
    +--------------------+
    1 row in set (0.00 sec)
  • ST_PointN( ) 函数 - 返回 LineString 中指定位置的点几何,LineString 中的点几何位置从 1 开始记,用法为 ST_PointN(ls, N)

    set @pointn:=ST_GeomFromText('LineString(1 1,5 5, 10 10 ,1 1)');
    select ST_AsText(ST_PointN(@pointn,1));
    +---------------------------------+
    | ST_AsText(ST_PointN(@pointn,1)) |
    +---------------------------------+
    | POINT(1 1)                      |
    +---------------------------------+
    1 row in set (0.00 sec)

面几何属性相关函数

  • ST_Area( ) 函数 - 返回 Polygon 或 MultiPolygon 参数在其 SRS 中测量的面积,用法为 ST_Area({poly|mpoly})

    • 如果几何对象是笛卡尔 SRS 中的有效 Polygon,则函数返回 Polygon 的面积
    • 如果几何对象是笛卡尔 SRS 中的有效 MultiPolygon,则函数返回 MultiPolygon 的面积之和
    • 如果几何对象是地理 SRS 中的有效 Polygon,则函数返回该 SRS 中多边形的大地测算面积(以平方米为单位)
    • 如果几何对象是地理 SRS 中的有效 MultiPolygon,则函数返回该 SRS 中多边形的大地测算面积之和(以平方米为单位)

    笛卡尔 SRS 示例:

    # 外环三角形的面积为 4.5,内环三角形的面积为 0.5,4.5 减去 0.5 等到 4
    SET @poly:=ST_GeomFromText('Polygon((0 0,0 3,3 0,0 0),(1 1,1 2,2 1,1 1))');
    select ST_Area(@poly);
    +----------------+
    | ST_Area(@poly) |
    +----------------+
    |              4 |
    +----------------+
    1 row in set (0.03 sec)
    
    # 外环矩形的面积为 9 ,内环矩形的面积为 1,9 减去 1 得到 8
    set @mpoly:=ST_GeomFromText('MultiPolygon(((0 0,0 3,3 3,3 0,0 0),(1 1,1 2,2 2,2 1,1 1)))');
    select ST_Area(@mpoly);
    +-----------------+
    | ST_Area(@mpoly) |
    +-----------------+
    |               8 |
    +-----------------+
    1 row in set (0.00 sec)

    地理 SRS 示例:

    # 由于以度为单位,因此函数返回的结果是一个近似值而非精准值
    select ST_Area(
        ST_GeomFromText('POLYGON((0 0, 0 3, 3 0, 0 0),(1 1, 1 2, 2 1, 1 1))', 4326)
    ) AS geographic_area;
    +--------------------+
    | geographic_area    |
    +--------------------+
    | 49262684495.757416 |
    +--------------------+
    1 row in set (0.00 sec)
  • ST_Centroid( ) 函数 - 以 Point 形式返回 Polygon 或 MultiPolygon 的质心(中心),用法为 ST_Centroid({poly|mpoly})

    set @poly:=ST_GeomFromText('POLYGON((0 0,10 0,10 10,0 10,0 0),(5 5,7 5,7 7,5 7,5 5))');
    select ST_GeometryType(@poly), ST_AsText(ST_Centroid(@poly));
    +------------------------+--------------------------------------------+
    | ST_GeometryType(@poly) | ST_AsText(ST_Centroid(@poly))              |
    +------------------------+--------------------------------------------+
    | POLYGON                | POINT(4.958333333333333 4.958333333333333) |
    +------------------------+--------------------------------------------+
    1 row in set (0.03 sec)

    请注意该函数的使用限制——如果几何对象使用了地理 SRS,执行该函数后会抛出 ER_NOT_IMPLEMENTED_FOR_GEOGRAPHIC_SRS 错误。换言之,MySQL 8.4 版本中的该函数不直接支持对地理 SRS 的质心计算。

  • ST_ExteriorRing( ) 函数 - 以 LineString 形式返回 Polygon 的外环,用法为 ST_ExteriorRing(poly)

    set @poly:=ST_GeomFromText('POLYGON((0 0,10 0,10 10,0 10,0 0),(5 5,7 5,7 7,5 7,5 5))');
    select ST_AsText(ST_ExteriorRing(@poly));
    +-------------------------------------+
    | ST_AsText(ST_ExteriorRing(@poly))   |
    +-------------------------------------+
    | LINESTRING(0 0,10 0,10 10,0 10,0 0) |
    +-------------------------------------+
    1 row in set (0.00 sec)
  • ST_InteriorRingN( ) 函数 - 以 LineString 形式返回第 N 个内环,用法为 ST_InteriorRingN(poly, N)。按照从外环到内环的顺序,环的值从 1 开始记。

    set @poly:=ST_GeomFromText('Polygon((0 0,0 3,3 3,3 0,0 0),(1 1,1 2,2 2,2 1,1 1))');
    select ST_AsText(ST_InteriorRingN(@poly,1));
    +--------------------------------------+
    | ST_AsText(ST_InteriorRingN(@poly,1)) |
    +--------------------------------------+
    | LINESTRING(1 1,1 2,2 2,2 1,1 1)      |
    +--------------------------------------+
    1 row in set (0.00 sec)
  • ST_NumInteriorRing( ) 函数 - 返回 Polygon 的内环数,用法为 ST_NumInteriorRing(poly)

    set @poly:=ST_GeomFromText('Polygon((0 0,0 3,3 3,3 0,0 0),(1 1,1 2,2 2,2 1,1 1))');
    select ST_NumInteriorRing(@poly);
    +---------------------------+
    | ST_NumInteriorRing(@poly) |
    +---------------------------+
    |                         1 |
    +---------------------------+
    1 row in set (0.00 sec)

空间关系相关函数

  • ST_Contains( ) 函数 - 返回 1 或 0 来判断是两个几何对象否存在完全包含关系,用法为 ST_Contains(g1,g2),若存在完全包含关系(g1 完全包含 g2,g1 和 g2 永远不相交),返回 1

    set @g1:=ST_GeomFromText('Polygon((0 0,0 3,3 3,3 0,0 0))'), 
    @p1:=ST_GeomFromText('Point(1 1)'),
    @p2:=ST_GeomFromText('Point(3 3)'),
    @p3:=ST_GeomFromText('Point(5 5)');
    
    select ST_Contains(@g1, @p1) as a, 
    ST_Within(@p1, @g1) as b,
    ST_Disjoint(@g1, @p1) as c,
    ST_Intersects(@g1, @p1) as d;
    +------+------+------+------+
    | a    | b    | c    | d    |
    +------+------+------+------+
    |    1 |    1 |    0 |    1 |
    +------+------+------+------+
    1 row in set (0.00 sec)
  • ST_Within( ) 函数 - 返回 0 或 1 来判断两个几何对象是否存在完全包含关系,用法为 ST_Within(g1,g2),若 g2 完全包含 g1,则返回 1

  • ST_Crosses( ) 函数 - 返回 0 或 1 来判断两个几何对象在空间上是否存在交叉关系,用法为 ST_Crosses(g1,g2)。有效交叉关系包括:

    • 线几何与面几何
    • 线几何与线几何

    点几何与线几何交叉会返回 0,面几何与点几何交叉会返回 NULL

  • ST_Equals( ) 函数 - 返回 0 或 1 来判断两个几何对象在空间上是否相等,用法为 ST_Equals(g1,g2),若 g1 等于 g2,则返回 1

  • ST_Intersects( ) 函数 - 返回 0 或 1 来判断两个几何对象在空间上是否存在相交关系,用法为 ST_Intersects(g1,g2)。有效相交关系包括:

    • 存在内部区域重叠(如两个多边形部分重叠)
    • 边界接触(如点在多边形边线上,线与多边形边界重叠)
    • 包含(一个几何对象完全在另外一个几何对象的内部)
    • 点与点重合(坐标相同)
    • 点落在线上
    • 点位于面的内部或边界
    • 线与面相交
    • 线与线交叉或部分重叠
    • 面与面边界接触或部分重叠
  • ST_Disjoint( ) 函数 - 返回 1 或 0 来判断两个几何对象在空间上是否不存在相交关系,用法为 ST_Disjoint(g1,g2),若不存在相交关系,则返回 1

  • ST_Distance( ) 函数 - 计算两个几何对象之间的距离,用法为 ST_Distance(g1, g2 [, unit])

    # 笛卡尔 SRS
    set @g1:=ST_GeomFromText('POINT(116.407396 39.904211)'), @g2:=ST_GeomFromText('POINT(121.473701 31.230416)');
    select ST_Distance(@g1,@g2);
    +----------------------+
    | ST_Distance(@g1,@g2) |
    +----------------------+
    |   10.045007021154834 |
    +----------------------+
    1 row in set (0.04 sec)
    
    # 地理 SRS
    ## 请注意!由于关联了 4326 这个 SRID,因此在 ST_GeomFromText 函数中默认必须纬度在前,经度在后,但可以通过该函数的 option 调整经纬度的顺序,如下:
    ## 以米为单位计算两个点几何的距离
    set @g1:=ST_GeomFromText('POINT(116.407396 39.904211)',4326,'axis-order=long-lat'),@g2:=ST_GeomFromText('POINT(121.473701 31.230416)',4326,'axis-order=long-lat');
    select ST_Distance(@g1,@g2,'metre');
    +----------------------+-------+
    | ST_Distance(@g1,@g2) | metre |
    +----------------------+-------+
    |   1065851.1029469664 | metre |
    +----------------------+-------+
    1 row in set (0.05 sec)
  • ST_Overlaps( ) 函数 - 用 0 或 1 来判断两个几何对象是否存在部分重叠但不完全包含的关系,主要应用于面几何和面几何,用法为 ST_Overlaps(g1, g2)

    set @g1:=ST_GeomFromText('POLYGON((0 0, 0 5, 5 5, 5 0, 0 0))'), @g2:=ST_GeomFromText('POLYGON((3 3, 3 8, 8 8, 8 3, 3 3))');
    SELECT ST_Overlaps(@g1, @g2);
    +-----------------------+
    | ST_Overlaps(@g1, @g2) |
    +-----------------------+
    |                     1 |
    +-----------------------+
    1 row in set (0.00 sec)
  • ST_Touches( ) 函数 - 用 0 或 1 来判断两个几何对象是否存在仅边界接触但无重叠部分的关系,用法为 ST_Touches(g1, g2)

    set @g1:=ST_GeomFromText('POLYGON((0 0, 0 5, 5 5, 5 0, 0 0))'), @g2:=ST_GeomFromText('POLYGON((5 0, 5 5, 10 5, 10 0, 5 0))');
    select ST_Touches(@g1,@g2);
    +---------------------+
    | ST_Touches(@g1,@g2) |
    +---------------------+
    |                   1 |
    +---------------------+
    1 row in set (0.00 sec)

几何计算函数

  • ST_Buffer( ) 函数 - 根据距离创建几何对象的缓冲区,用法为 ST_Buffer(g, d [, strategy1 [, strategy2 [, strategy3]]]),g 表示几何对象,d 表示以米为单位的距离(不能是负数),后面的参数表示创建缓冲区时最多三个可选策略(策略需要使用 ST_Buffer_Strategy( ) 函数进行生成)

    set @pt:=ST_GeomFromText('POINT(0 0)');
    SET @pt_strategy:=ST_Buffer_Strategy('point_square');
    select ST_AsText(ST_Buffer(@pt, 2, @pt_strategy));
    +--------------------------------------------+
    | ST_AsText(ST_Buffer(@pt, 2, @pt_strategy)) |
    +--------------------------------------------+
    | POLYGON((-2 -2,2 -2,2 2,-2 2,-2 -2))       |
    +--------------------------------------------+
    1 row in set (0.00 sec)
  • ST_Buffer_Strategy( ) 函数 - 返回策略的字符串,用法为 ST_Buffer_Strategy(strategy [, points_per_circle])

    第一个参数必须是:

    • 对于 point 策略,允许的值有 'point_circle' 和 'point_square'
    • 对于 join 策略,允许的值有 'join_round' 和 'join_miter'.
    • 对于 end 策略,允许的值有 'end_round' 和 'end_flat'

    若第一个参数是 'point_circle'、 'join_round'、 'join_miter' 或 'end_round',则 points_per_circle 参数必须是正数值。points_per_circle 参数的最大值即系统变量 max_points_in_geometry 的值。

  • ST_Difference( ) 函数 - 以几何对象方式返回两个几何对象的差集,用法为 ST_Difference(g1, g2),函数返回 g1 减去 g1 与 g2 的交集部分

    select ST_AsText(ST_Difference(
    ST_GeomFromText('POLYGON((0 0,0 5,5 5,5 0,0 0))'),
    ST_GeomFromText('POLYGON((1 1,1 4,4 4,4 1,1 1))')
    )) as diff;
    +------------------------------------------------------+
    | diff                                                 |
    +------------------------------------------------------+
    | POLYGON((0 0,5 0,5 5,0 5,0 0),(1 1,1 4,4 4,4 1,1 1)) |
    +------------------------------------------------------+
    1 row in set (0.00 sec)
  • ST_Intersection( ) 函数 - 以几何对象方式返回两个几何对象的交集,用法为 ST_Intersection(g1, g2)

    set @g1:=ST_GeomFromText('LineString(1 1, 3 3)'), @g2:=ST_GeomFromText('LineString(1 3, 3 1)');
    select ST_AsText(ST_Intersection(@g1, @g2)) as a;
    +------------+
    | a          |
    +------------+
    | POINT(2 2) |
    +------------+
    1 row in set (0.00 sec)
  • ST_Union( ) 函数 - 以几何对象方式返回两个几何对象的并集,用法为 ST_Union(g1, g2)

    set @g1:=ST_GeomFromText('LineString(1 1, 3 3)'), @g2:=ST_GeomFromText('LineString(1 3, 3 1)');
    select ST_AsText(ST_Union(@g1,@g2)) as b;
    +--------------------------------------+
    | b                                    |
    +--------------------------------------+
    | MULTILINESTRING((1 1,3 3),(1 3,3 1)) |
    +--------------------------------------+
    1 row in set (0.00 sec)

辅助函数

  • ST_GeomFromText( ) 函数 - 将 WKT 格式的字符串转换为数据库可识别的几何对象,用法为 ST_GeomFromText(wkt [, srid [, options]])。前面说过了,对于地理 SRS,若输入的是 WKT 格式的点几何,则默认是纬度在前,经度在后,可通过 option 调整顺序

    # 正确语法
    set @g1:=ST_GeomFromText('POINT(116.407396 39.904211)',4326,'axis-order=long-lat');
    set @g2:=ST_GeomFromText('POINT(121.473701 31.230416)',4326,'axis-order=long-lat');
    
    # 错误语法
    set @g1:=ST_GeomFromText('POINT(116.407396 39.904211)',4326);
    ERROR 3617 (22S03): Latitude 116.407396 is out of range in function st_geomfromtext. It must be within [-90.000000, 90.000000].
  • ST_GeomFromWKB( ) 函数 - 将 WKB 格式的字符串转换为数据库可识别的几何对象,用法为 ST_GeomFromWKB(wkb [, srid [, options]])

  • ST_AsText( ) 函数或 ST_AsWKT( ) 函数 - 将几何对象转换为 WKT 格式,用法为 ST_AsText(g [, options])

  • ST_AsWKB( ) 函数或 ST_AsBinary( ) 函数 - 将几何对象转换为 WKB 格式,用法为 ST_AsWKB(g [, options])

  • ST_SRID( ) 函数 - 返回几何对象的有效 SRID

    set @g:=ST_GeomFromText('LineString(1 1,2 2)', 0);
    select ST_SRID(@g);
    +-------------+
    | ST_SRID(@g) |
    +-------------+
    |           0 |
    +-------------+
    1 row in set (0.00 sec)
  • ST_Transform( ) 函数 - 将几何对象从当前的 SRID 转换到另外一个 SRID,用法为 ST_Transform(g, target_srid),target_srid 支持 EPSG 的所有 SRID,但是以下除外:

    • EPSG:1042
    • EPSG:1043
    • EPSG:9816
    • EPSG:9826

    例子如下:

    set @p:=ST_GeomFromText('POINT(52.381389 13.064444)', 4326);
    select ST_AsText(@p);
    +----------------------------+
    | ST_AsText(@p)              |
    +----------------------------+
    | POINT(52.381389 13.064444) |
    +----------------------------+
    1 row in set (0.00 sec)
    
    set @p:=ST_Transform(@p, 4230);
    select ST_AsText(@p);
    +---------------------------------------------+
    | ST_AsText(@p)                               |
    +---------------------------------------------+
    | POINT(52.38208611407426 13.065520672345304) |
    +---------------------------------------------+
    1 row in set (0.00 sec)
  • ST_Validate( ) 函数 - 验证几何对象是否合法有效,用法为 ST_Validate(g)。如果几何对象有效,则原样返回,否则返回 NULL 或者输出错误提示

    set @ls1:=ST_GeomFromText('LINESTRING(0 0, 1 1)');
    
    select ST_AsText(ST_Validate(@ls1));
    +------------------------------+
    | ST_AsText(ST_Validate(@ls1)) |
    +------------------------------+
    | LINESTRING(0 0,1 1)          |
    +------------------------------+
    1 row in set (0.00 sec)

注意点

  • 对于笛卡尔 SRS,无论是点几何、线几何、面几何以及几何形状集合,在书写表示和输出时,其都是横坐标在前且纵坐标在后
  • 对于地理 SRS,由于需要符合 EPSG 的标准,无论是点几何、线几何、面几何以及几何形状集合,在书写表示和输出时,其都是纬度在前且经度在后
Avatar photo

关于 陸風睿

GNU/Linux 从业者、开源爱好者、技术钻研者,撰写文档既是兴趣也是工作内容之一。Q - "281957576";WeChat - "jiulongxiaotianci",Github - https://github.com/jimcat8
用一杯咖啡支持我们,我们的每一篇[文档]都经过实际操作和精心打磨,而不是简单地从网上复制粘贴。期间投入了大量心血,只为能够真正帮助到您。
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇