PostGIS导入Shapefile?常用命令是什么?
很多同学在把矢量数据入库时,第一反应就是搜索“PostGIS导入Shapefile?常用命令是什么?”。这篇文章只解决一个具体问题:如何用常见命令把 Shapefile 稳定导入 PostgreSQL/PostGIS,并知道每个关键参数什么时候该用。

引言:PostGIS导入Shapefile最常用的是哪条命令
在 PostGIS 中导入 Shapefile,最常见的命令有两类:一类是 PostGIS 自带的 shp2pgsql,另一类是 GDAL 提供的 ogr2ogr。如果只是把一个本地 Shapefile 导入数据库,shp2pgsql 通常更直接;如果涉及格式转换、批处理、字段映射或多数据源,ogr2ogr 更灵活。
最常用的 shp2pgsql 命令格式如下:
shp2pgsql -I -s 4326 -W UTF-8 your_data.shp public.your_table | psql -h localhost -p 5432 -U postgres -d gisdb
这条命令的含义是:读取 your_data.shp,指定坐标系 SRID 为 4326,按 UTF-8 读取属性编码,导入到 gisdb 数据库的 public.your_table 表中,并自动创建空间索引。
背景:为什么PostGIS导入Shapefile经常出错
Shapefile 是 GIS 中非常常见的矢量数据格式,但它并不是一个单文件格式。一个完整的 Shapefile 通常至少包含以下文件:
.shp:几何图形文件,存储点、线、面坐标。.shx:几何索引文件。.dbf:属性表文件。.prj:坐标系定义文件,可能缺失或不规范。.cpg:字符编码文件,常用于说明属性字段编码。
PostGIS导入Shapefile失败,常见原因不是命令本身复杂,而是数据源存在以下问题:
- Shapefile 缺少
.prj,无法确认坐标系。 - 中文字段或中文属性乱码,编码参数设置错误。
- 表名、字段名包含中文、空格、特殊符号或过长。
- 几何类型混杂,例如面图层里混入 MultiPolygon 或无效几何。
- 目标数据库没有启用 PostGIS 扩展。
- Windows 命令行路径包含空格,但没有加引号。
因此,正确的入库流程不是直接复制一条命令,而是先确认坐标系、编码、目标库和目标表结构。
原理:shp2pgsql命令到底做了什么
shp2pgsql 并不是直接把 Shapefile 写进数据库。它的工作原理是把 Shapefile 转换成一段 SQL 语句,然后再交给 psql 执行。
例如下面这条命令:
shp2pgsql -I -s 4490 -W GBK data/county.shp public.county | psql -U postgres -d gisdb
可以理解为两个步骤:
shp2pgsql读取county.shp,生成创建表、插入属性和几何、创建空间索引的 SQL。psql连接 PostgreSQL 数据库,把这些 SQL 执行到gisdb中。
PostGIS 中的空间数据会存储在 geometry 或 geography 字段中。Shapefile 导入时通常使用 geometry 字段。SRID 是空间参考系统编号,例如 4326 代表 WGS 84,经纬度坐标;4490 代表 CGCS2000 地理坐标系;常见 Web 墨卡托为 3857。
需要注意:-s 参数只是告诉 PostGIS 这个数据的坐标系编号,并不一定执行坐标转换。如果原始 Shapefile 是 CGCS2000,却错误指定为 4326,数据可能看起来位置接近,但坐标系元数据已经错了。
步骤:使用shp2pgsql导入Shapefile到PostGIS
步骤1:确认数据库已经启用PostGIS扩展
先进入 PostgreSQL 数据库,确认目标数据库已经安装 PostGIS 扩展:
psql -h localhost -p 5432 -U postgres -d gisdb
进入数据库后执行:
CREATE EXTENSION IF NOT EXISTS postgis;
检查 PostGIS 是否可用:
SELECT postgis_full_version();
如果能返回 PostGIS 版本信息,说明数据库具备存储和查询空间数据的能力。
步骤2:确认Shapefile文件完整
在导入前,至少确认同一目录下存在这些文件:
county.shp
county.shx
county.dbf
county.prj
如果缺少 .shx 或 .dbf,导入通常会失败。如果缺少 .prj,仍然可能导入,但需要你自己确认 SRID,否则后续叠加分析、距离计算、WebGIS 显示都容易出错。
步骤3:确认坐标系SRID
可以用 QGIS 打开 Shapefile,右键图层选择属性,查看源坐标参考系。也可以使用 GDAL 命令检查:
ogrinfo -al -so county.shp
如果数据是 WGS 84,经常使用:
-s 4326
如果数据是 CGCS2000,经常使用:
-s 4490
如果数据是 Web Mercator,经常使用:
-s 3857
如果是投影坐标系,例如高斯克吕格、UTM 或地方坐标系,需要根据 .prj 或数据提供方说明确定准确 EPSG 编号。
步骤4:执行最常用的shp2pgsql导入命令
假设数据库名为 gisdb,用户名为 postgres,Shapefile 为 county.shp,目标表为 public.county,坐标系为 4490,可以执行:
shp2pgsql -I -s 4490 -W UTF-8 county.shp public.county | psql -h localhost -p 5432 -U postgres -d gisdb
常用参数解释如下:
| 参数 | 作用 | 使用建议 |
|---|---|---|
-I |
导入后创建 GiST 空间索引 | 建议保留,后续空间查询更快 |
-s 4490 |
指定几何字段的 SRID | 必须与原始数据真实坐标系一致 |
-W UTF-8 |
指定属性表字符编码 | 中文乱码时重点检查 |
county.shp |
输入 Shapefile 路径 | 路径有空格时加引号 |
public.county |
目标 schema 和表名 | 建议使用英文小写和下划线 |
psql -d gisdb |
连接目标数据库并执行 SQL | 确认数据库名、用户、端口正确 |
步骤5:如果中文乱码,改用GBK或GB18030
国内很多历史 Shapefile 的属性表编码是 GBK 或 GB18030。如果导入后中文变成乱码,可以尝试:
shp2pgsql -I -s 4490 -W GBK county.shp public.county | psql -h localhost -p 5432 -U postgres -d gisdb
或者:
shp2pgsql -I -s 4490 -W GB18030 county.shp public.county | psql -h localhost -p 5432 -U postgres -d gisdb
如果 Shapefile 旁边存在 .cpg 文件,可以先打开查看里面写的是 UTF-8、GBK、936 还是其他编码。936 通常可按 GBK 处理。
步骤6:导入后检查表和几何字段
导入完成后,不要马上认为成功。建议执行以下检查:
SELECT COUNT(*) FROM public.county;
检查 SRID:
SELECT ST_SRID(geom) AS srid, COUNT(*)
FROM public.county
GROUP BY ST_SRID(geom);
检查几何类型:
SELECT GeometryType(geom) AS geom_type, COUNT(*)
FROM public.county
GROUP BY GeometryType(geom);
检查空间范围:
SELECT ST_Extent(geom) FROM public.county;
如果是经纬度数据,范围通常应接近经度、纬度数值,例如中国区域经度大致在 70 到 140,纬度大致在 15 到 55。若出现几百万的坐标值,说明它可能是投影坐标系,不应简单指定为 4326。
步骤7:如果需要追加数据,使用-a参数
如果目标表已经存在,只想把同结构的新 Shapefile 追加进去,可以使用 -a:
shp2pgsql -a -s 4490 -W UTF-8 county_part2.shp public.county | psql -h localhost -p 5432 -U postgres -d gisdb
注意,追加数据要求字段结构和几何类型基本一致。如果字段名不一致或字段类型冲突,可能会导入失败。
步骤8:如果需要删除旧表重建,使用-d参数
如果目标表已经存在,希望先删除再重新导入,可以使用 -d:
shp2pgsql -d -I -s 4490 -W UTF-8 county.shp public.county | psql -h localhost -p 5432 -U postgres -d gisdb
注意:-d 会删除同名表。生产数据库中使用前必须确认是否有其他业务依赖该表。
步骤:使用ogr2ogr导入Shapefile到PostGIS
除了 shp2pgsql,ogr2ogr 也是 PostGIS导入Shapefile 的常用命令。它适合需要转换格式、重投影、覆盖图层、指定几何字段名的场景。
基本命令如下:
ogr2ogr -f "PostgreSQL" PG:"host=localhost port=5432 dbname=gisdb user=postgres password=your_password" county.shp -nln public.county -lco GEOMETRY_NAME=geom -lco FID=gid -lco SPATIAL_INDEX=GIST
如果要在导入时指定或转换坐标系,可以使用:
ogr2ogr -f "PostgreSQL" PG:"host=localhost port=5432 dbname=gisdb user=postgres password=your_password" county.shp -nln public.county -a_srs EPSG:4490
-a_srs 是指定数据坐标系,不做坐标转换。如果要真正重投影,应使用 -t_srs:
ogr2ogr -f "PostgreSQL" PG:"host=localhost port=5432 dbname=gisdb user=postgres password=your_password" county.shp -nln public.county_4326 -t_srs EPSG:4326
如果原始数据坐标系信息缺失,但你确认它是 CGCS2000,并希望转换到 WGS 84,可以组合使用:
ogr2ogr -f "PostgreSQL" PG:"host=localhost port=5432 dbname=gisdb user=postgres password=your_password" county.shp -nln public.county_4326 -s_srs EPSG:4490 -t_srs EPSG:4326
常见坑:PostGIS导入Shapefile失败时优先检查这些问题
坑1:把指定SRID误认为坐标转换
shp2pgsql -s 4326 主要是给几何字段写入 SRID。它不会自动把高斯投影坐标转换成经纬度。如果需要转换坐标系,可以先用 QGIS 另存为目标 CRS,或用 ogr2ogr -t_srs 重投影。
坑2:中文乱码只改数据库编码还不够
PostgreSQL 数据库通常建议使用 UTF-8,但 Shapefile 的 .dbf 可能是 GBK。PostGIS导入Shapefile中文乱码时,重点检查 -W 参数,而不是只改数据库编码。
坑3:表名和字段名不规范
Shapefile 字段名有长度限制,且历史数据中常见中文字段、括号、空格。导入数据库后,建议统一使用英文小写字段名,例如 name、code、area、type。如果是正式项目,最好先在 QGIS、ArcGIS Pro 或 Python 中整理字段。
坑4:Windows路径没有加引号
如果路径中包含空格,例如:
D:GIS Datacounty.shp
命令中应写成:
"D:GIS Datacounty.shp"
否则命令行会把路径拆开,导致找不到文件。
坑5:目标数据库没有postgis扩展
如果出现 geometry 类型不存在、函数不存在等错误,通常是目标数据库没有执行:
CREATE EXTENSION postgis;
注意,PostGIS 扩展是按数据库启用的,不是只在 PostgreSQL 实例上安装一次就所有库都自动可用。
坑6:几何无效导致后续分析失败
有些 Shapefile 可以成功导入,但后续做叠加、裁剪、相交查询时报错。这通常与无效几何有关。可以检查:
SELECT COUNT(*)
FROM public.county
WHERE NOT ST_IsValid(geom);
如果存在无效几何,可尝试:
UPDATE public.county
SET geom = ST_MakeValid(geom)
WHERE NOT ST_IsValid(geom);
但 ST_MakeValid 可能改变几何类型,例如 Polygon 变成 MultiPolygon 或 GeometryCollection,正式处理前应抽样检查结果。
方法比较:shp2pgsql和ogr2ogr该选哪个
| 对比项 | shp2pgsql | ogr2ogr |
|---|---|---|
| 适合场景 | 单个 Shapefile 快速导入 PostGIS | 多格式转换、重投影、批处理、复杂导入 |
| 学习成本 | 较低,参数相对集中 | 稍高,参数体系更大 |
| 坐标转换 | 主要指定 SRID,不适合直接重投影 | 支持 -s_srs 和 -t_srs 重投影 |
| 编码处理 | 常用 -W 指定编码 |
可结合 GDAL 配置和图层选项处理 |
| 空间索引 | -I 创建 GiST 索引 |
-lco SPATIAL_INDEX=GIST 创建索引 |
| 推荐用法 | 日常入库首选 | 数据转换和自动化流程首选 |
简单判断:如果你只是问 PostGIS导入Shapefile常用命令是什么,优先掌握 shp2pgsql;如果你还需要重投影、转换 GeoJSON、批量处理目录中的数据,再学习 ogr2ogr。
检查清单:导入前后逐项确认
- 确认目标数据库已执行
CREATE EXTENSION postgis;。 - 确认 Shapefile 至少包含
.shp、.shx、.dbf。 - 确认
.prj是否存在,并核对真实坐标系。 - 确认 SRID 参数正确,例如
4326、4490、3857。 - 确认中文属性编码,必要时尝试
-W UTF-8、-W GBK或-W GB18030。 - 确认目标表名使用英文小写和下划线。
- 导入后执行
COUNT(*)检查记录数。 - 导入后执行
ST_SRID检查坐标系编号。 - 导入后执行
ST_Extent检查空间范围是否合理。 - 导入后检查是否存在无效几何。
- 正式库中谨慎使用
-d删除重建表。
FAQ:PostGIS导入Shapefile常见问题
PostGIS导入Shapefile最常用命令是什么?
最常用的是:
shp2pgsql -I -s 4326 -W UTF-8 data.shp public.data | psql -h localhost -p 5432 -U postgres -d gisdb
其中 -I 表示创建空间索引,-s 表示指定 SRID,-W 表示指定属性编码。
shp2pgsql导入Shapefile时-s参数必须写吗?
建议写。-s 用于设置几何字段的 SRID。没有正确 SRID 的空间表,在后续空间分析、距离计算、坐标转换和 WebGIS 发布时很容易出问题。
PostGIS导入Shapefile中文乱码怎么办?
优先检查 Shapefile 的属性编码。常见解决方式是把 -W UTF-8 改为 -W GBK 或 -W GB18030。如果有 .cpg 文件,可以先查看其编码声明。
shp2pgsql能把投影坐标转换成经纬度吗?
一般不建议用 shp2pgsql 做坐标转换。-s 主要用于指定 SRID。需要真正重投影时,建议使用 QGIS 另存为目标坐标系,或使用 ogr2ogr -t_srs EPSG:4326。
导入后为什么在地图上位置不对?
常见原因是 SRID 写错、原始 Shapefile 的 .prj 不准确、投影坐标被当成经纬度、或 WebGIS 前端没有正确处理坐标系。可以先用 ST_SRID 和 ST_Extent 检查数据库中的坐标范围。
PostGIS导入Shapefile需要创建空间索引吗?
建议创建。空间索引能明显改善 ST_Intersects、ST_Within、ST_DWithin 等空间查询的性能。使用 shp2pgsql 时加 -I 即可创建 GiST 空间索引。
已经有同名表时怎么办?
如果要追加数据,使用 -a;如果要删除旧表并重建,使用 -d;如果不确定旧表是否还有用,不要直接使用 -d。生产环境中建议先备份表或导入到临时表。
可以批量导入多个Shapefile吗?
可以。Windows 可以写批处理脚本,Linux 或 macOS 可以写 shell 脚本。批量导入时要特别注意每个 Shapefile 的坐标系、编码和表名是否一致,不要为了省事给所有数据套同一个 SRID。
结论:先掌握shp2pgsql,再根据场景使用ogr2ogr
PostGIS导入Shapefile的核心命令并不复杂,日常最常用的是 shp2pgsql -I -s SRID -W 编码 文件.shp schema.表名 | psql ...。真正容易出问题的是坐标系、中文编码、表名字段名、空间索引和无效几何。
如果你的目标是快速把 Shapefile 入库,优先使用 shp2pgsql;如果你需要重投影、格式转换或构建自动化数据处理流程,再使用 ogr2ogr。无论使用哪种方法,导入后都应检查记录数、SRID、几何类型和空间范围,这样才能保证 PostGIS 中的数据可查询、可分析、可发布。