如何将SQL Server中的Geometry类型数据导入PostGIS Geometry类型列
解决SQL Server十六进制Geometry数据导入PostgreSQL的方法
我来帮你搞定这个SQL Server到PostgreSQL的空间数据迁移问题,之前处理过好几个类似的需求,两种方法都很靠谱,你可以根据自己的情况选:
方法一:用ogr2ogr直接迁移(推荐,自动处理格式转换)
这是最省心的方式,不用手动处理十六进制转换,GDAL的ogr2ogr工具会自动搞定SQL Server和PostGIS之间的空间格式兼容。
安装GDAL工具:
- Windows:从OSGeo4W安装包(选择GDAL组件),或者直接下载预编译版本。
- Linux:用包管理器安装,比如
apt install gdal-bin(Debian/Ubuntu)或yum install gdal(CentOS/RHEL)。
执行迁移命令:
替换命令里的数据库连接信息,直接把SQL Server的数据同步到PostgreSQL:ogr2ogr -f "PostgreSQL" PG:"dbname=你的目标库名 user=你的PG用户名 password=你的PG密码 host=PG服务器地址" MSSQL:"server=SQLServer地址;database=SQLServer库名;UID=SQLServer用户名;PWD=SQLServer密码" -nln boundary_polygon -sql "SELECT id, shape FROM boundary_polygon"-nln指定PostgreSQL里的目标表名-sql用来筛选需要迁移的列,确保只取id和shape
方法二:处理已导出的十六进制CSV文件
如果已经把数据导出成了包含id和十六进制shape的CSV文件,可以用PostgreSQL的函数手动转换格式:
步骤1:准备工作
- 确保你的PostgreSQL数据库已经安装了PostGIS扩展(没有的话先执行):
CREATE EXTENSION IF NOT EXISTS postgis; - 检查导出的CSV:确保shape列的十六进制字符串没有
0x前缀(如果有,后面转换时要去掉),每行格式类似1,010300000001000000040000000000000000000000...
步骤2:导入临时表并转换
创建临时表存储原始CSV数据:
CREATE TEMP TABLE temp_boundary (id int, shape_hex text);把CSV数据导入临时表(替换文件路径):
COPY temp_boundary FROM '/你的文件路径/boundary_polygon_export.csv' WITH (FORMAT csv, HEADER);- 如果是远程服务器,可能需要用
\copy命令(psql里的)或者把文件传到服务器上。
- 如果是远程服务器,可能需要用
转换格式并插入目标表:
这里要注意SQL Server的Geometry二进制格式前面有6个字节的额外信息(版本号+SRID),需要去掉后再转换成PostGIS支持的WKB:INSERT INTO boundary_polygon (id, shape) SELECT id, ST_SetSRID( ST_GeomFromWKB(decode(substring(shape_hex, 13), 'hex')), -- 去掉前6个字节(对应12个十六进制字符) 4326 -- 替换成你的空间参考ID,比如WGS84是4326,必须和SQL Server里的SRID一致 ) FROM temp_boundary;- 如果你的十六进制字符串有
0x前缀,把substring(shape_hex,13)改成substring(shape_hex,15)(先去掉0x的2个字符,再去掉前面6个字节的12个字符)。 - 一定要确认SRID和SQL Server中的一致,否则空间数据会出现坐标偏移。
- 如果你的十六进制字符串有
常见问题排查
- 导入后空间数据显示异常:先检查SRID是否匹配,SQL Server里的
shape.STSrid可以查看原数据的SRID,PostgreSQL里用ST_SRID(shape)验证。 - 转换报错:检查十六进制字符串是否完整,有没有被截断,或者有没有特殊字符干扰。
内容的提问来源于stack exchange,提问作者ashok




