2

更新:

是的,就是这样!

就像 mloskot 说的那样,整个表都需要被倾倒。使用 sql 选择字段会丢失有关字段宽度的信息。

谢谢,解决了!

大家好,

我对ogr2ogr有疑问。我正在尝试将 PostgreSQL 表格转储到 Shapefile。ogr2ogr 似乎改变了整数和字符等数据类型的大小。

这是 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,我刚刚安装了它。

4

1 回答 1

5

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

是的,整数宽度和字符宽度的正确值 11 和 80 分别是OGR 驱动程序为 ESRI Shapefile设置的默认值

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

比较这两个输出:

查询整个表

$ 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 有疑问,您可以尝试使用 Shapelib 中的 shpdump 和 dbfdump 实用程序检查您的输出 Shapefile 文件(.shp .dbf)。该软件使用与 GDAL/OGR 中使用的完全相同的 C 代码来处理 Shapefile 数据。

于 2010-02-03T01:15:24.333 回答