MySQL ST_MakeEnvelope 怎样从两个点构造矩形范围
来源:17golang原创
时间:2026-10-27 08:14:02 429浏览 收藏
在做“按两个坐标点筛选一块范围”的查询时,我更愿意先把范围本身表达成一个几何对象,而不是手写四个角点。MySQL 的 ST_MakeEnvelope() 就是为这个任务准备的:给它两个 Point,它会在笛卡尔坐标平面上返回两点的包络范围。
官方地址:https://dev.mysql.com/doc/refman/8.4/en/spatial-convenience-functions.html
先记住一个容易忽略的细节:返回值不一定永远是 Polygon。两点重合时返回 Point;只在水平或垂直方向对齐时返回 LineString;只有一般的对角点关系才返回 Polygon。下面按这个边界把 SQL 跑通。
先把两个坐标点准备好
函数签名只有两个参数:ST_MakeEnvelope(pt1, pt2)。参数必须是 Point,点的顺序不影响最终包络范围,但坐标的含义要在业务侧先约定清楚。示例用平面坐标,不把经纬度直接当成地球曲面距离。
-- 用 WKT 创建两个 Point;这里的 x、y 是抽象笛卡尔坐标
SET @pt1 = ST_GeomFromText('POINT(10 20)');
SET @pt2 = ST_GeomFromText('POINT(30 50)');
-- 先确认输入确实是点,避免把 LineString 等其他几何类型传进去
SELECT ST_GeometryType(@pt1) AS pt1_type,
ST_GeometryType(@pt2) AS pt2_type;
如果你的表字段已经是空间类型,可以直接把字段或变量传入,不必先转换成 WKT。WKT 更适合在示例、脚本参数和排查时明确表达输入。
用 ST_MakeEnvelope 生成矩形范围
把两个 Point 传入函数,再用 ST_AsText() 转成容易阅读的 WKT。对于 (10,20) 和 (30,50) 这样的普通对角点,返回的闭合 Polygon 会依次经过左下、右下、右上、左上,再回到起点。
-- 两个点是矩形的对角点,函数会补出另外两个角 SELECT ST_AsText(ST_MakeEnvelope(@pt1, @pt2)) AS envelope_wkt; -- 同时读取几何类型,避免把所有结果都假设成 Polygon SELECT ST_GeometryType(ST_MakeEnvelope(@pt1, @pt2)) AS envelope_type;
普通情况下会得到类似 POLYGON((10 20,30 20,30 50,10 50,10 20)) 的结果。这里的闭合首尾相同,是多边形环的正常表达。

三种点位关系对应三种返回形态
这一步是实际使用中最容易踩坑的地方:函数描述的是“包络”,不是“强制生成一个面积大于零的矩形”。当两个点的几何关系退化时,结果也会退化。
| 两个点的关系 | 返回类型 | 适合怎样处理 |
|---|---|---|
| 坐标完全相同 | Point | 表示一个位置,不能按面来计算面积 |
| 仅 x 相同或仅 y 相同 | LineString | 表示水平或垂直线段,先判断类型再做空间运算 |
| x、y 都不同 | Polygon | 表示普通矩形包络,可继续用于面关系判断 |
-- 用三个案例观察退化结果;每个案例都读取文本和类型
SELECT 'same-point' AS case_name,
ST_AsText(ST_MakeEnvelope(
ST_GeomFromText('POINT(10 20)'),
ST_GeomFromText('POINT(10 20)')
)) AS result_wkt,
ST_GeometryType(ST_MakeEnvelope(
ST_GeomFromText('POINT(10 20)'),
ST_GeomFromText('POINT(10 20)')
)) AS result_type
UNION ALL
SELECT 'vertical-line',
ST_AsText(ST_MakeEnvelope(
ST_GeomFromText('POINT(10 20)'),
ST_GeomFromText('POINT(10 50)')
)),
ST_GeometryType(ST_MakeEnvelope(
ST_GeomFromText('POINT(10 20)'),
ST_GeomFromText('POINT(10 50)')
));
如果后续 SQL 必须使用 Polygon 的面积、外环或面关系,建议在应用层先判断 ST_GeometryType(),或者在输入校验阶段要求两个点的 x 与 y 都不同。不要等到后续空间函数报错才猜测原因。

生产查询前检查 SRID 与坐标边界
这个函数的计算是在笛卡尔坐标系中完成的,结果几何的 SRID 为 0。因此,如果业务字段使用的是有明确空间参考的几何对象,不要把“构造包络”误认为“已经完成经纬度地理计算”。地图范围、距离和投影转换属于另外的空间问题,应在明确坐标系后单独设计。
官方规则还给出几项硬边界:
- 两个参数必须都是 Point,否则会产生参数错误。
- 任一点坐标为无穷大或 NaN 时,会产生 GIS 无效数据错误。
- 地理空间参考系统不支持这个函数的调用。
- 涉及多个几何参数的空间函数通常要求参数处于同一 SRS;不要混用不同空间参考。
-- 发布前记录结果类型和 SRID,便于排查坐标系误解
SELECT ST_GeometryType(envelope) AS geometry_type,
ST_SRID(envelope) AS result_srid,
ST_AsText(envelope) AS result_wkt
FROM (
SELECT ST_MakeEnvelope(
ST_GeomFromText('POINT(10 20)'),
ST_GeomFromText('POINT(30 50)')
) AS envelope
) AS prepared_range;
这段查询的重点不是多包一层子查询,而是把“结果类型、SRID、可读文本”一起记录下来。排查坐标范围为空、面积为零或和地图预期不一致时,这三个字段通常比只看一段 WKT 更快定位问题。
和业务表做范围筛选时怎么落地
如果表里保存的是 Point,可以把包络作为一个明确的查询参数,再结合实际空间关系函数使用。这里不把示例包装成某个固定业务表结构,避免让字段名掩盖核心逻辑;关键是先确认两端使用同一套坐标约定,并在 SQL 中保留参数来源。
-- 先构造范围参数;实际项目中可替换为绑定参数
SET @range = ST_MakeEnvelope(
ST_GeomFromText('POINT(10 20)'),
ST_GeomFromText('POINT(30 50)')
);
-- 假设 locations.position 是 Point;先用类型与范围条件表达业务意图
SELECT id, name
FROM locations
WHERE ST_Within(position, @range); -- 只返回位于包络范围内的点
真正上线时还要结合表结构、索引和数据规模选择执行方式。ST_MakeEnvelope() 负责构造几何范围,不会自动替你完成空间索引设计,也不会替你判断输入坐标到底是平面坐标还是经纬度。
常见问题
ST_MakeEnvelope 可以直接传经纬度吗?
它按笛卡尔坐标平面计算,不能把调用结果直接当成球面或椭球面上的地理范围。若数据使用地理 SRS,先按业务坐标系重新设计空间运算。
为什么两个点传进去却不是 Polygon?
两点重合会退化为 Point,水平或垂直对齐会退化为 LineString。只有 x 和 y 都不同的普通对角点关系才返回 Polygon。
能否用一个 Point 和一个字符串参数?
不能。两个参数都需要是 Point;字符串应先通过合适的几何构造函数转换,并在转换后确认类型和坐标边界。
怎样确认生成的范围是预期的?
同时读取 ST_AsText()、ST_GeometryType() 和 ST_SRID(),再核对两个输入点的坐标顺序。不要只根据一张地图截图判断函数是否正确。
总结
MySQL ST_MakeEnvelope(pt1, pt2) 的用法可以压缩成三句话:两个参数必须是 Point;普通对角点生成 Polygon;重合或水平/垂直对齐会产生退化的 Point 或 LineString。把返回类型和 SRID 一并记录,范围查询就不会因为“看起来像矩形”而掩盖坐标系和几何类型问题。
-
501 收藏
-
501 收藏
-
501 收藏
-
501 收藏
-
501 收藏
-
430 收藏
-
289 收藏
-
264 收藏
-
279 收藏
-
330 收藏
-
198 收藏
-
381 收藏
-
296 收藏
-
488 收藏
-
399 收藏
-
387 收藏
-
384 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 立即学习 543次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 立即学习 516次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 立即学习 500次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 立即学习 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 立即学习 485次学习