PostgreSQL/PostGIS-高级驱动程序信息

该页中收集的信息处理高级主题,在 OGR PostgreSQL driver Information 页。

多个几何列

PostgreSQL驱动程序支持访问具有多个PostGIS几何列的表。

OGR支持读取、更新、创建具有多个PostGIS几何列的表(如下 RFC 41:支持OGR中的多个几何字段 )对于这样的表,一个OGR层将报告尽可能多的几何字段,因为表中有几何列。

为了向后兼容,还可以使用GetLayerByName()查询一个名为“foo(bar)”的层,其中“foo”是一个表,“bar”是一个几何列。

即使启用了PostGIS,如果用户定义了环境变量

PG_LIST_ALL_TABLES=YES

(and does not specify tables=), all regular user tables and named views will be treated as layers. However, tables with multiple geometry column will only be reported once in that mode. So this variable is mainly useful when PostGIS is enabled to find out tables with no spatial data, or views without an entry in geometry_columns table.

在任何情况下,都可以使用GetLayerByName()显式查询所有用户表

可以访问常规(非空间)表,并将返回具有属性的要素,但不返回几何图形。如果表格有“wkb_geometry”字段,则将其视为空间表格。检查字段的类型以确定如何读取它。它可以是一个PostGIS 几何学 字段,假定返回到OGC WKT中,或键入BYTEA或OID,在这种情况下,它用作OGC WKB几何图形的源。

支持从空间表继承的表。

如果有一个“ogc_fid”字段,它将用于设置特征的特征id,而不是作为常规字段处理。

层名称的格式可以是“schema.table”。架构必须存在,并且用户需要对目标架构和公共架构具有写权限。

如果用户定义了环境变量

PG_SKIP_VIEWS=YES

(并且未指定tables=),只有常规用户表将被视为层。默认操作是包含视图。当您希望将数据复制到其他格式,同时避免视图中的冗余数据时,此变量特别有用。

命名视图

当对访问的数据库启用PostGIS时,只要在 geometry_columns 桌子。但是,请注意AddGeometryColumn()SQL函数不接受为视图添加条目(仅适用于常规表)。因此,这通常必须使用以下SQL语句手动完成:

"INSERT INTO geometry_columns VALUES ( '', 'public', 'name_of_my_view', 'name_of_geometry_column', 2, 4326, 'POINT');"

也可以使用命名视图,而不在geometry_columns表中插入行。为此,需要在连接字符串的“tables=”选项中显式指定视图的名称。见上文。缺点是OGR无法报告有效的SRS并找出正确的几何类型。

检索新插入特征的FID

在非复制模式下,使用CreateFeature()插入到表中的功能的FID(通常是该功能的OGCu FID列的值)将从数据库中检索,并可以使用GetFID()获取。这种新行为的一个副作用是,如果在进行插入的循环中重复使用同一个feature对象,则必须小心。在第一次迭代之后,FID将被设置为非空值,因此在第二次迭代时,CreateFeature()将尝试使用上一个功能的FID插入新功能,这将失败,因为您无法使用相同的FID插入两个功能。因此,在这种情况下,必须在调用CreateFeature()之前显式重置FID,或者使用新的feature对象。

Python中的代码片段示例:

feat = ogr.Feature(lyr.GetLayerDefn())
for i in range(100):
    feat.SetFID(-1)  # Reset FID to null value
    lyr.CreateFeature(feat)
    print('The feature has been assigned FID %d' % feat.GetFID())

或:

for i in range(100):
    feat = ogr.Feature(lyr.GetLayerDefn())
    lyr.CreateFeature(feat)
    print('The feature has been assigned FID %d' % feat.GetFID())

通过设置配置选项可以获得旧的GDAL行为 OGR_PG_RETRIEVE_FID 错误的。

交易问题

PostgreSQL中高效的顺序读取需要在事务中完成(从技术上讲,这是一个不带HOLD的游标)。因此,一旦检索到某个特性,如果当前没有打开任何事务,PG驱动程序将隐式打开此类事务。如果调用ResetReading(),则将释放此事务(前提是没有其他层仍在读取)。

如果在这样的隐式事务中,发出显式数据集级别的StartTransaction(),则PG驱动程序将使用保存点正确模拟事务行为,同时使读取层上的活动游标仍然打开。

如果在读取层之前使用数据集级别StartTransaction()打开显式事务,则此事务将用于在层上迭代的游标。当显式提交或回滚事务时,游标将变为无效,应再次发出ResetReading()以从头开始重新读取。

由于调用SetAttributeFilter()或SetSpatialFilter()意味着隐式的ResetReading(),因此它们与ResetReading()具有相同的效果。也就是说,当隐式事务正在进行时,将提交该事务(如果没有读取其他层),并在下一个GetNextFeature()调用时重新启动一个新的事务。相反,如果在显式事务中调用它们,则维护该事务。

使用上述规则,下面的示例显示了在不同场景中使用OGR API时运行的SQL指令。

lyr1->GetNextFeature()             BEGIN (implicit)
                                   DECLARE cur1 CURSOR FOR SELECT * FROM lyr1
                                   FETCH 1 IN cur1

lyr1->SetAttributeFilter('xxx')
     --> lyr1->ResetReading()      CLOSE cur1
                                   COMMIT (implicit)

lyr1->GetNextFeature()             BEGIN (implicit)
                                   DECLARE cur1 CURSOR  FOR SELECT * FROM lyr1 WHERE xxx
                                   FETCH 1 IN cur1

lyr2->GetNextFeature()             DECLARE cur2 CURSOR  FOR SELECT * FROM lyr2
                                   FETCH 1 IN cur2

lyr1->GetNextFeature()             FETCH 1 IN cur1

lyr2->GetNextFeature()             FETCH 1 IN cur2

lyr1->CreateFeature(f)             INSERT INTO cur1 ...

lyr1->SetAttributeFilter('xxx')
     --> lyr1->ResetReading()      CLOSE cur1
                                   COMMIT (implicit)

lyr1->GetNextFeature()             DECLARE cur1 CURSOR  FOR SELECT * FROM lyr1 WHERE xxx
                                   FETCH 1 IN cur1

lyr1->ResetReading()               CLOSE cur1

lyr2->ResetReading()               CLOSE cur2
                                   COMMIT (implicit)

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

ds->StartTransaction()             BEGIN

lyr1->GetNextFeature()             DECLARE cur1 CURSOR FOR SELECT * FROM lyr1
                                   FETCH 1 IN cur1

lyr2->GetNextFeature()             DECLARE cur2 CURSOR FOR SELECT * FROM lyr2
                                   FETCH 1 IN cur2

lyr1->CreateFeature(f)             INSERT INTO cur1 ...

lyr1->SetAttributeFilter('xxx')
     --> lyr1->ResetReading()      CLOSE cur1
                                   COMMIT (implicit)

lyr1->GetNextFeature()             DECLARE cur1 CURSOR  FOR SELECT * FROM lyr1 WHERE xxx
                                   FETCH 1 IN cur1

lyr1->ResetReading()               CLOSE cur1

lyr2->ResetReading()               CLOSE cur2

ds->CommitTransaction()            COMMIT

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

ds->StartTransaction()             BEGIN

lyr1->GetNextFeature()             DECLARE cur1 CURSOR FOR SELECT * FROM lyr1
                                   FETCH 1 IN cur1

lyr1->CreateFeature(f)             INSERT INTO cur1 ...

ds->CommitTransaction()            CLOSE cur1 (implicit)
                                   COMMIT

lyr1->GetNextFeature()             FETCH 1 IN cur1      ==> Error since the cursor was closed with the commit. Explicit ResetReading() required before

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

lyr1->GetNextFeature()             BEGIN (implicit)
                                   DECLARE cur1 CURSOR FOR SELECT * FROM lyr1
                                   FETCH 1 IN cur1

ds->StartTransaction()             SAVEPOINT savepoint

lyr1->CreateFeature(f)             INSERT INTO cur1 ...

ds->CommitTransaction()            RELEASE SAVEPOINT savepoint

lyr1->ResetReading()               CLOSE cur1
                                   COMMIT (implicit)

注意:实际上,PG驱动程序一次获取500个特性。取1是为了解释清楚。

高级示例

  • 此示例显示使用ogrinfo仅列出 tables= 选项。

    ogrinfo -ro PG:'dbname=warmerda tables=table1,table2'
    
  • 此示例显示如何使用ogrinfo查询具有多个几何列(“geom1”和“geom2”)的表“foo”。

    ogrinfo -ro -al PG:dbname=warmerda 'foo(geom2)'
    
  • 这个例子展示了如何只列出模式apt200810和apt200812中的层。图层名将以其所属架构的名称作为前缀。

    ogrinfo -ro PG:'dbname=warmerda schemas=apt200810,apt200812'
    
  • 这个例子显示了使用ogrinfo只列出名为apt200810的模式中的层。请注意,由于只列出了一个架构,因此层名称不会以apt200810作为前缀。

    ogrinfo -ro PG:'dbname=warmerda schemas=apt200810'
    
  • 本例展示如何将apt200810目录中的一组shapefile转换为现有Postgres模式apt200810。在该示例中,我们可以改用schemas=选项。

    ogr2ogr -f PostgreSQL "PG:dbname=warmerda active_schema=apt200810" apt200810
    
  • 本例显示如何将架构apt200810中的所有表转换为apt200810目录中的一组shapefile。注意,由于只列出了一个模式,图层名不会以apt200810为前缀

    ogr2ogr apt200810 PG:'dbname=warmerda schemas=apt200810'
    
  • 此示例显示如何覆盖现有架构中的现有表。注意使用-nln指定限定图层名。

    ogr2ogr -overwrite -f PostgreSQL "PG:dbname=warmerda" mytable.shp mytable -nln myschema.mytable
    

    注意,在这种情况下,使用-lco SCHEMA=mytable而不是-nln是行不通的(请参见 #2821 了解更多详细信息)。

    如果需要同时覆盖架构中的许多表,-nln选项不太合适,因此使用活动架构连接字符串可能更方便。如有必要,以下示例将覆盖apt200810目录中与一组shapefile相对应的所有PostgreSQL表:

    ogr2ogr -overwrite -f PostgreSQL "PG:dbname=warmerda active_schema=apt200810" apt200810
    

也见