PostGIS空间扩展与空间数据基础
1 文章背景PostGIS 是 PostgreSQL 的空间数据库扩展。开启 PostGIS 后PostgreSQL 就可以存储和处理点、线、面等空间数据并支持空间索引、空间查询、坐标系管理和空间分析函数。本文主要整理如何在 PostgreSQL 中开启 PostGIS 扩展以及常见空间数据类型、WKT 数据写入、空间字段查询和spatial_ref_sys表的基本含义。2 准备工作在开启 PostGIS 扩展之前需要先完成以下准备① 已经安装 PostgreSQL。② 已经安装 PostGIS 扩展。③ 已经创建需要启用空间能力的数据库。④ 当前数据库用户具有创建扩展的权限。PostGIS 是在具体数据库中启用的而不是只要安装一次就对所有数据库自动生效。因此每个需要空间能力的数据库都要单独执行扩展创建语句。3 开启 PostGIS 扩展进入目标数据库后执行CREATEEXTENSION postgis;执行成功后当前数据库就具备了 PostGIS 空间能力。如果希望检查当前数据库是否已经启用 PostGIS可以执行SELECTPostGIS_Version();如果能够返回版本信息说明 PostGIS 已经可用。4 使用 Python 开启扩展也可以通过 Python 执行 SQL 语句开启扩展。importpsycopg2 connpsycopg2.connect(databasedata_database,userusername,passwordpassword,host127.0.0.1,port5432)cursorconn.cursor()cursor.execute(CREATE EXTENSION IF NOT EXISTS postgis;)conn.commit()cursor.close()conn.close()这里使用CREATE EXTENSION IF NOT EXISTS postgis;可以避免扩展已存在时报错。5 spatial_ref_sys 表开启 PostGIS 后数据库中会出现spatial_ref_sys表。该表用于存储空间参考系统信息。常见字段如下①srid空间参考标识符是空间参考系统的唯一编号。②auth_name授权机构名称例如EPSG。③auth_srid授权机构分配的空间参考编号。④srtext空间参考系统的 WKT 描述。⑤proj4text空间参考系统的 Proj.4 描述。例如常见的 WGS84 经纬度坐标系对应的 EPSG 编码是4326。6 常见空间数据类型PostGIS 支持多种空间数据类型。①Point点。②MultiPoint多点。③LineString线。④MultiLineString多线。⑤Polygon多边形。⑥MultiPolygon多多边形。⑦GeometryCollection几何集合。实际建表时通常使用geometry字段并指定具体几何类型和 SRID。7 创建点要素表创建一个点要素表CREATETABLEpoint_table(idSERIALPRIMARYKEY,nameVARCHAR(255)NOTNULL,geomgeometry(Point,4326));其中①geometry(Point, 4326)表示该字段存储点几何。②4326表示空间参考系统为 WGS84 经纬度坐标系。8 插入点数据可以使用ST_GeomFromText()将 WKT 字符串转换为空间几何对象。INSERTINTOpoint_table(name,geom)VALUES(point_1,ST_GeomFromText(POINT(113.65 34.76),4326));也可以使用ST_Point()创建点INSERTINTOpoint_table(name,geom)VALUES(point_2,ST_SetSRID(ST_Point(113.70,34.80),4326));需要注意常见 WKT 点坐标顺序是POINT(x y)如果是经纬度数据一般写作POINT(经度 纬度)。9 查询空间数据直接查询geom字段时结果可能不是易读文本。可以使用ST_AsText()转换为 WKT。SELECTid,name,ST_AsText(geom)ASwktFROMpoint_table;如果需要查看 SRIDSELECTid,name,ST_SRID(geom)ASsridFROMpoint_table;10 创建线要素表CREATETABLEline_table(idSERIALPRIMARYKEY,nameVARCHAR(255),geomgeometry(LineString,4326));插入线数据INSERTINTOline_table(name,geom)VALUES(line_1,ST_GeomFromText(LINESTRING(113.65 34.76, 113.70 34.80, 113.75 34.82),4326));查询为 WKTSELECTid,name,ST_AsText(geom)ASwktFROMline_table;11 创建面要素表CREATETABLEpolygon_table(idSERIALPRIMARYKEY,nameVARCHAR(255),geomgeometry(Polygon,4326));插入面数据INSERTINTOpolygon_table(name,geom)VALUES(polygon_1,ST_GeomFromText(POLYGON((113.60 34.70, 113.80 34.70, 113.80 34.90, 113.60 34.90, 113.60 34.70)),4326));多边形 WKT 需要闭合也就是首尾坐标点相同。12 从经纬度字段生成空间字段如果表中已有lon和lat字段可以添加空间字段ALTERTABLEpoint_tableADDCOLUMNgeom_newgeometry(Point,4326);然后根据经纬度字段更新UPDATEpoint_tableSETgeom_newST_SetSRID(ST_Point(lon,lat),4326);如果要把一个表中的经纬度转换后写入另一个表可以使用INSERTINTOnew_point_table(id,geom)SELECTid,ST_SetSRID(ST_Point(lon,lat),4326)FROMsource_table;13 修改空间字段坐标系如果只是给没有 SRID 的几何设置 SRID可以使用UPDATEpoint_tableSETgeomST_SetSRID(geom,4326);如果需要真正进行坐标转换应使用ST_Transform()UPDATEpoint_tableSETgeomST_Transform(geom,3857);两者区别是①ST_SetSRID()只是声明或修改 SRID 标记不改变坐标值。②ST_Transform()会进行真实坐标转换坐标值会发生变化。14 删除空间数据删除空间数据和删除普通表数据类似DELETEFROMpoint_tableWHEREid1;执行删除前建议先查询确认目标记录。15 小结PostGIS 的核心是让 PostgreSQL 具备空间数据管理能力。入门时可以先掌握三个重点开启postgis扩展使用geometry字段存储空间对象使用ST_GeomFromText()、ST_AsText()、ST_SetSRID()等函数完成空间数据的写入和查询。掌握这些基础后就可以继续学习空间索引、缓冲区分析、相交判断、距离计算和坐标转换等更深入的空间分析能力。