从PG到SHP的ogr2ogr改变了.DBF中的数据类型

时间:2010-02-02 11:26:17

标签: postgresql gis shapefile gdal

更新

是的,就是这样!

像mloskot所说,需要倾倒整个表格。选择带有sql的字段会丢失有关字段宽度的信息。

谢谢,修好了!

大家好,

我遇到ogr2ogr的问题。我正在尝试将PostgreSQL表格转储到Shapefile。 ogr2ogr似乎改变了整数和char等数据类型的大小。

这是读取Shapefile集的DB结构的一部分:

Table "test"
nd_1 - numeric(8,0)
nd_2 - numeric(2,0)
nd_3 - numeric(2,0)
nd_9 - character varying(60)

它看起来很正确。

这是有趣的开始:

ogr2ogr air5000.shp "PG: [...]" sql 'select
CAST(nd_1 AS INTEGER),
CAST(nd_2 AS INTEGER),
CAST(nd_3 as INTEGER),
CAST(ND_9 AS CHARACTER VARYING(60))
from test' ;

然后

dbview -e test.dbf 

Field Name Type Length Decimal Pos
nd 1 - N - 11 - 0
nd 2 - N - 11 - 0
nd 3 - N - 11 - 0
nd 9 - C - 80 - 0

num-length从 8,2,2 变为 11 ,char长度从 10 变为 80

如果没有指定宽度(长度),我读到这些是默认值。

如何指定宽度?

我尝试使用或不使用强制转换的每个组合,如下所示:

select
CAST(nd_1 AS NUMERIC),
CAST(nd_2 AS NUMERIC),
CAST(nd_3 as NUMERIC),
CAST(ND_9 AS CHARACTER VARYING(60))

dbview中提供:

Field Name Type Length Decimal Pos
nd 1 - N - 24 - 15
nd 2 - N - 24 - 15
nd 3 - N - 24 - 15
nd 9 - C - 80 - 0

没有投射(select * from test)给出

Field Name      Type    Length  Decimal Pos
nd 1 - N - 24 - 15
nd 2 - N - 24 - 15
nd 3 - N - 24 - 15
nd 9 - C - 80 - 0

在任何场合都不会靠近原件。

debugfile [--debug on]没有给出任何特别的恕我直言,这是我试过的3 ogr2ogr命令的输出:

PG: PQexec(DECLARE executeSQLCursor CURSOR for select CAST(nd_1 AS INTEGER), CAST(nd_2 AS INTEGER), CAST(nd_3 as INTEGER), CAST(ND_9 AS CHARACTER VARYING(60)) from test)
PG: PQexec(DECLARE OGRPGResultLayerReader CURSOR for select CAST(nd_1 AS INTEGER), CAST(nd_2 AS INTEGER), CAST(nd_3 as INTEGER), CAST(ND_9 AS CHARACTER VARYING(60)) from test)
PG: PQexec(DECLARE OGRPGResultLayerReader CURSOR for select CAST(nd_1 AS INTEGER), CAST(nd_2 AS INTEGER), CAST(nd_3 as INTEGER), CAST(ND_9 AS CHARACTER VARYING(60)) from test)
PG: 2 features read on layer 'sql_statement'.

PG: PQexec(DECLARE executeSQLCursor CURSOR for select CAST(nd_1 AS NUMERIC), CAST(nd_2 AS NUMERIC), CAST(nd_3 as NUMERIC), CAST(ND_9 AS CHARACTER VARYING(60)) from test)
PG: PQexec(DECLARE OGRPGResultLayerReader CURSOR for select CAST(nd_1 AS NUMERIC), CAST(nd_2 AS NUMERIC), CAST(nd_3 as NUMERIC), CAST(ND_9 AS CHARACTER VARYING(60)) from test)
PG: PQexec(DECLARE OGRPGResultLayerReader CURSOR for select CAST(nd_1 AS NUMERIC), CAST(nd_2 AS NUMERIC), CAST(nd_3 as NUMERIC), CAST(ND_9 AS CHARACTER VARYING(60)) from test)
PG: 2 features read on layer 'sql_statement'.
PG: PQexec(DECLARE executeSQLCursor CURSOR for select * from test)
PG: PQexec(DECLARE OGRPGResultLayerReader CURSOR for select * from test)
PG: PQexec(DECLARE OGRPGResultLayerReader CURSOR for select * from test)
PG: 2 features read on layer 'sql_statement'.

我也试过-dsco precision=no,但这也没有帮助。

也许dbview正在拉我的腿,但是它显示了Shapefile的源.dbf标题设置正确。

任何想法?

EJ

更新: 你好mloskot,

感谢您的回复和重新格式化,非常感谢!

我在使用GDAL 1.6.3。

我尝试指定宽度,但它没有什么区别。

ogr2ogr test.shp "PG: [...] " -sql 'select CAST(nd_1 AS INTEGER), CAST(nd_2 AS numeric(2,0)), CAST(nd_3 as NUMERIC(2,0)) from test' ;

给出:

Field Name  Type    Length  Decimal Pos
nd 1          N    11       0
nd 2          N    24      15
nd 3          N    24      15

是的,我尝试指定没有强制转换的字段,如下所示:

ogr2ogr air5000.shp "PG: [...] "-sql 'select nd_1, nd_2, nd_3, ND_9 from test'

给出:

 Field Name Type    Length  Decimal Pos
nd 1          N    24      15
nd 2          N    24      15
nd 3          N    24      15
nd 9          C    80       0

试图

integer(field_length)

CAST(nd_2 AS INTEGER(2))

不起作用,给出错误

ERROR 1: ERROR: current transaction is aborted, commands ignored until end of transaction block

也许我的Postgresql和PostGIS版本已过时了? Postgres = 8.3.5,PostGIS = 1.3.3

我会检查Shapelib,我刚才安装它。

1 个答案:

答案 0 :(得分:5)

首先,您没有指定您使用的GDAL / OGR版本,因此可能很难诊断出问题所在。请注意,正在从版本到版本应用改进。

是的,分别是整数宽度和字符宽度的正确值11和80,是OGR driver for ESRI Shapefile设置的默认值

问题是您使用SQL查询仅从表中获取某些行 这导致OGR PG driver驱动程序不保留字段宽度。

比较这两个输出:

查询整个表

$ ogrinfo PG:dbname=test test_ogr
Layer name: test_ogr
Geometry: Point
Feature Count: 1
Extent: (1.000000, 2.000000) - (1.000000, 2.000000)
Layer SRS WKT:
(unknown)
FID Column = id
Geometry Column = geom
n3: String (60.0)
n1: Integer (8.0)
n2: Integer (2.0)
OGRFeature(test_ogr):1
  n3 (String) = abcdefg
  n1 (Integer) = 12345678
  n2 (Integer) = 12
  POINT (1 2)

相同的查询,但手动指定的SQL选择

$ ogrinfo PG:dbname=test -sql "SELECT n1, n2, n3, geom FROM test_ogr"
Layer name: sql_statement
Geometry: Unknown (any)
Feature Count: 1
Extent: (1.000000, 2.000000) - (1.000000, 2.000000)
Layer SRS WKT:
(unknown)
Geometry Column = geom
n1: Real (0.0)
n2: Real (0.0)
n3: String (0.0)
OGRFeature(sql_statement):0
  n1 (Real) = 12345678
  n2 (Real) = 12
  n3 (String) = abcdefg
  POINT (1 2)

如您所见,第二个选项完全丢失了字段属性,这就是OGR的工作方式。

以下是两个输出的相同示例,但转换为Shapefile:

转储test_ogr

中的所有数据
$ ogr2ogr -f "ESRI Shapefile" test.shp PG:dbname=test test_ogr
$ dbfdump -h test.dbf
Field 0: Type=C/String, Title=`n3', Width=60, Decimals=0
Field 1: Type=N/Integer, Title=`n1', Width=8, Decimals=0
Field 2: Type=N/Integer, Title=`n2', Width=2, Decimals=0
n3                                                                 n1 n2
abcdefg                                                      12345678 12

使用-sql选项和SELECT查询:

$ ogr2ogr -f "ESRI Shapefile" test.shp PG:dbname=test -sql "SELECT n1, n2, n3, geom FROM test_ogr"
$ dbfdump -h test.dbf
Field 0: Type=N/Double, Title=`n1', Width=24, Decimals=15
Field 1: Type=N/Double, Title=`n2', Width=24, Decimals=15
Field 2: Type=C/String, Title=`n3', Width=80, Decimals=0
                      n1                       n2 n3
12345678.000000000000000       12.000000000000000 abcdefg

因此,为了准确保留所有属性,您需要转储所有表而不指定SQL查询。

顺便说一下,如果你怀疑是重视dbfview,你可以尝试使用shpdump and dbfdump中的Shapelib实用程序检查输出Shapefile文件(.shp,.dbf)。该软件使用与GDAL / OGR中使用的完全相同的C代码来处理Shapefile数据。