概述
本章,您将学习 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 标识(
-
笛卡尔 SRS(Cartesian SRS):指一个没有指定地理坐标系的平面坐标系,常用于局部坐标系或假设的平面地图,如建筑平面图设计、仓库货架定位系统、电路板元件布局、游戏地图坐标
-
地理 SRS:使用经纬度坐标表示地球表面位置的地理坐标系,常用于城市级地图应用、全球物流跟踪、地理信息系统(GIS)、任何涉及地球曲率的应用
Q:什么是 SRID?
用来唯一标识 SRS 的一种数值编码,其类似于现实世界中各个国家的邮政编码(每个国家的邮政编码规则都不同),不同 SRID 对应不同的坐标系统定义,确保空间数据的准确解析与转换,常有:
- 4326 - 经纬度
- 3857 - 网页地图
- 4490 - 中国北斗导航系统
所有的 SRID 可通过 该网站 进行查询。
-
几何对象:MySQL 在处理空间数据时,需要使用相关的函数(如 ST_GeomFromText( ) 函数)将 WKT 或 WKB 格式的字符串转换为数据库可识别的几何类型。
-
质心(Centroid):几何学中的一个重要概念,也称为几何中心或重心。对于均匀材质的物体,质心就是质量的中心点。
空间数据类型
GEOMETRY
是所有空间几何类型的超类(Superclass),可以表示任何几何形状(点、线、面、集合体等),其子类(或称派生类)包括:
POINT
- 用来表示一个点的坐标,常用来存储经纬度坐标。有关经纬度的知识,请参阅 前面 Redis 的书写内容。LINESTRING
- 表示由多个点连接而成的线POLYGON
- 表示一个多边形,其由多个点组成的闭区间MULTIPOINT
- 多个点的集合MULTILINESTRING
- 多条线的集合MULTIPOLYGON
- 表示多个多边形的集合GEOMETRYCOLLECTION
- 表示多种几何形状的集合(如同时包含点、线、面)。
空间数据类型的格式
两种标准空间数据格式:
- WKT(Well-Known Text)格式 - 以 ASCII 格式交换几何数据
- WKB(Well-Known Binary)格式 - 以二进制流形式交换几何数据
WKT 格式
-
对于
POINT
:POINT(15 20)
横坐标在前,纵坐标在后,横坐标与纵坐标使用空格分隔(而不是用逗号)。若定义了 SRID,则 15 表示纬度,20 表示经度。
-
对于
LINESTRING
:LINESTRING(0 0, 10 10, 20 25, 50 60)
这是由四个点连接而成的线,每个点使用逗号进行分隔。
-
对于
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)构成的小矩形
-
对于
MULTIPOINT
:MULTIPOINT(0 0, 20 20, 60 60)
-
对于
MULTILINESTRING
:MULTILINESTRING((10 10, 20 20), (15 15, 30 15))
-
对于
MULTIPOLYGON
:MULTIPOLYGON(((0 0,10 0,10 10,0 10,0 0)),((5 5,7 5,7 7,5 7, 5 5)))
-
对于
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
);
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 中规定,
POINT
或MULTIPOINT
的维度为 0,LINESTRING
或MULTILINETRING
的维度为 1,POLYGON
或MULTIPOLYGON
的维度为 2select 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 永远不相交),返回 1set @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 的标准,无论是点几何、线几何、面几何以及几何形状集合,在书写表示和输出时,其都是纬度在前且经度在后
