PostgreSQL + PostGIS(SQL操作)

一、PostgreSQL常用操作:

1.创建数据库:

sql 复制代码
-- 创建名为gis_db数据库
CREATE DATABASE gis_db;

2.连接到数据库:

bash 复制代码
# 操作系统 shell 中
psql -d gis_db -U postgres

3.创建表:

sql 复制代码
-- 创建一个存储小区信息的表,包含空间字段 geom(多边形,SRID 4326)
CREATE TABLE residential_zones (
    id SERIAL PRIMARY KEY,
    name VARCHAR(100),
    geom GEOMETRY(Polygon, 4326)
);
3.1 基础几何类型(OGC 标准)
类型 说明
Point
LineString 线(由多个点连接而成)
Polygon 多边形(由外环和零或多个内环组成)
MultiPoint 多点集合
MultiLineString 多线集合
MultiPolygon 多多边形集合
GeometryCollection 混合几何集合(可包含上述任意类型)

3.2 曲面类型(PostGIS 扩展 / SQL-MM 标准)
类型 说明
CircularString 由圆弧段组成的线
CompoundCurve 由直线段和圆弧段混合组成的线
CurvePolygon 由曲线(含圆弧)构成边界的多边形
MultiCurve 多曲线集合
MultiSurface 多曲面集合

3.3 带 Z(高程)或 M(测量值)的变体

上述所有类型都可以带 Z(三维)、M(测量值)或 ZM(两者都有),例如:

  • PointZ

  • LineStringM

  • PolygonZM

在创建表时,也可直接使用 GEOMETRY(PointZ, 4326) 这样的约束。(只需将 Polygon 替换成其他几何类型名称即可

4.插入数据:

sql 复制代码
-- 插入一个多边形(小区边界),坐标顺序必须闭合(首尾相同)
INSERT INTO residential_zones (name, geom)
VALUES (
    '东方花园',
    ST_GeomFromText('POLYGON((116.40 39.90, 116.41 39.90, 116.41 39.91, 116.40 39.91, 116.40 39.90))', 4326)
);

5.查询数据:

sql 复制代码
-- 查询所有小区
SELECT * FROM residential_zones;

-- 查询 id 为 1 的小区名称和几何对象
SELECT name, ST_AsText(geom) FROM residential_zones WHERE id = 1;

6.更新数据:

sql 复制代码
-- 将 id 为 1 的小区名称改为"东方花园(一期)"
UPDATE residential_zones SET name = '东方花园(一期)' WHERE id = 1;

-- 查询所有小区
SELECT * FROM residential_zones;

7.删除数据:

sql 复制代码
-- 删除 id 为 2 的小区记录
DELETE FROM residential_zones WHERE id = 2;

8.创建索引:

sql 复制代码
-- 为 geom 字段创建 GIST 空间索引(强烈推荐,提升空间查询性能)
CREATE INDEX idx_residential_zones_geom ON residential_zones USING GIST (geom);

9.执行事务:

sql 复制代码
-- 开启事务,连续执行两条更新,若出错则全部回滚
BEGIN;
    UPDATE residential_zones SET name = 'A区' WHERE id = 1;
    UPDATE residential_zones SET name = 'B区' WHERE id = 2;
COMMIT;  -- 提交事务
-- 若要回滚,使用 ROLLBACK;

10.添加PostGIS扩展:

sql 复制代码
-- 在数据库中启用 PostGIS 扩展(只需执行一次)
CREATE EXTENSION IF NOT EXISTS postgis;

二、PostGIS常用的空间查询语句

1.查询包含在指定几何对象内部的所有要素:

sql 复制代码
-- 查询完全位于某个大矩形内部的小区
SELECT name 
FROM residential_zones
WHERE ST_Within(
    geom, 
    ST_GeomFromText('POLYGON((116.38 39.88, 116.42 39.88, 116.42 39.92, 116.38 39.92, 116.38 39.88))', 4326)
);

2.查询与指定几何对象相交的所有要素:

sql 复制代码
-- 查询与一个圆形缓冲区相交的小区(缓冲区中心点 116.40,39.90,半径 200 米)
SELECT name 
FROM residential_zones
WHERE ST_Intersects(
    geom, 
    ST_Buffer(ST_SetSRID(ST_MakePoint(116.40, 39.90), 4326)::geography, 200)::geometry
);

3.查询距离给定几何对象最近的要素:

sql 复制代码
-- 查询离点 (116.405, 39.905) 最近的小区,并返回距离
SELECT name, 
       ST_Distance(geom::geography, ST_SetSRID(ST_MakePoint(116.405, 39.905), 4326)::geography) AS distance_m
FROM residential_zones
ORDER BY geom::geography <-> ST_SetSRID(ST_MakePoint(116.405, 39.905), 4326)::geography
LIMIT 1;

4.查询在指定距离内与给定几何对象相交的所有要素:

sql 复制代码
-- 查询距离点 (116.40,39.90) 500 米范围内的小区
SELECT name 
FROM residential_zones
WHERE ST_DWithin(
    geom::geography, 
    ST_SetSRID(ST_MakePoint(116.40, 39.90), 4326)::geography, 
    500
);

5.查询要素的面积:

sql 复制代码
-- 查询每个小区的面积(平方米)
SELECT name, ST_Area(geom::geography) AS area_m2
FROM residential_zones;

6.查询要素的长度:

sql 复制代码
-- 假设有一条河流表 rivers,包含线状字段 geom
SELECT name, ST_Length(geom::geography) AS length_m
FROM rivers;

三、PostGIS常用的空间关系判断语句

以下均以 residential_zones(多边形)和 point_of_interest(点表)为例。

  • ST_Equals(A, B):判断两个几何体是否完全相同

    sql 复制代码
    SELECT ST_Equals(geom1, geom2) FROM ...;
  • ST_Intersects(A, B):判断是否相交

    sql 复制代码
    SELECT name FROM residential_zones 
    WHERE ST_Intersects(geom, ST_SetSRID(ST_MakePoint(116.40,39.90), 4326));
  • ST_Contains(A, B):判断 A 是否包含 B

    sql 复制代码
    SELECT r.name FROM residential_zones r, point_of_interest p
    WHERE ST_Contains(r.geom, p.geom) AND p.id = 1;
  • ST_Within(A, B):判断 A 是否在 B 内部

    sql 复制代码
    SELECT p.name FROM point_of_interest p, residential_zones r
    WHERE ST_Within(p.geom, r.geom) AND r.name = '东方花园';
  • ST_Touches(A, B):判断两个几何体是否接触(边界有公共点)

    sql 复制代码
    SELECT a.name, b.name 
    FROM residential_zones a, residential_zones b
    WHERE ST_Touches(a.geom, b.geom) AND a.id != b.id;
  • ST_Overlaps(A, B):判断两个几何体是否重叠(同维度相交但不包含)

    sql 复制代码
    SELECT a.name, b.name 
    FROM residential_zones a, residential_zones b
    WHERE ST_Overlaps(a.geom, b.geom);
  • ST_Crosses(A, B):判断是否交叉(如线穿过面)

    sql 复制代码
    -- 假设 roads 表有线状几何
    SELECT r.name 
    FROM roads r, residential_zones z
    WHERE ST_Crosses(r.geom, z.geom);
  • ST_Disjoint(A, B):判断是否不相交

    sql 复制代码
    SELECT name FROM residential_zones 
    WHERE ST_Disjoint(geom, ST_SetSRID(ST_MakePoint(116.40,39.90), 4326));
  • ST_DWithin(A, B, distance):判断是否在指定距离内

    sql 复制代码
    SELECT name FROM residential_zones 
    WHERE ST_DWithin(geom::geography, ST_SetSRID(ST_MakePoint(116.40,39.90), 4326)::geography, 500);

四、数据导入导出语句

  • 导出整个数据库

    bash 复制代码
    pg_dump -U postgres -h localhost gis_db > gis_db_backup.sql
    复制代码
  • 导出特定表

    bash 复制代码
    pg_dump -U postgres -h localhost -t residential_zones gis_db > residential_zones_backup.sql
  • 导入 SQL 文件

    bash 复制代码
    psql -U postgres -h localhost gis_db < gis_db_backup.sql
  • 使用 COPY 导出 CSV

    sql 复制代码
    -- 将 residential_zones 表导出为 CSV,包含表头
    COPY residential_zones (id, name, ST_AsText(geom)) 
    TO '/tmp/residential_zones.csv' WITH CSV HEADER;
    复制代码
  • 使用 COPY 导入 CSV

    sql 复制代码
    -- 假设已有表结构,导入 CSV 数据(需确保几何字段为 WKT 文本)
    COPY residential_zones (id, name, geom) 
    FROM '/tmp/residential_zones.csv' WITH CSV HEADER;
    复制代码
  • 导入 Shapefile 到 PostGIS

    bash 复制代码
    # 使用 shp2pgsql 将 shapefile 转换为 SQL 并导入数据库
    shp2pgsql -s 4326 /path/to/housing.shp residential_zones | psql -d gis_db -U postgres
  • 导出 PostGIS 表为 Shapefile

    bash 复制代码
    # 使用 pgsql2shp 导出表为 shapefile
    pgsql2shp -f /tmp/housing.shp -h localhost -u postgres gis_db residential_zones
    复制代码
相关推荐
博语小屋19 分钟前
I/O 多路转接之epoll
运维·服务器·数据库
问道飞鱼1 小时前
【大模型学习】LangGraph 深度解析:定义、功能、原理与实践
数据库·学习·大模型·工作流
DJ斯特拉1 小时前
黑马点评技术汇总(四)缓存雪崩 && 缓存击穿
数据库·缓存
lzhdim1 小时前
SQL 入门 7:SQL 聚合与分组:函数、GROUP BY 与 ROLLUP
java·服务器·数据库·sql·mysql
lifewange1 小时前
INSERT INTO ... SELECT ...
数据库·sql
Uso_Magic1 小时前
SQLSERVER__EXPLAIN 常用分析案例。
服务器·数据库·sql
IAtlantiscsdn2 小时前
Redis面试题总结
数据库·redis·缓存
2501_924952692 小时前
自动化机器学习(AutoML)库TPOT使用指南
jvm·数据库·python
诗酒当趁年华2 小时前
langchain核心组件1-智能体
数据库·langchain
流星白龙2 小时前
【MySQL】9.MySQL内置函数
android·数据库·mysql