OGR-SQL方言

GDALDataset支持通过 GDALDataset::ExecuteSQL() 方法。虽然理论上任何类型的命令都可以用这种方式处理,但实际上该机制用于向应用程序提供SQL SELECT功能的子集。本页讨论OGR中实现的通用SQL实现,并讨论特定于驱动程序的SQL支持问题。

另一种“方言”,SQLite方言,可以用来代替OGRSQL方言。参考 SQL SQLite方言 有关详细信息,请参见第页。

OGRLayer类还支持对使用 OGRLayer::SetAttributeFilter() 方法。属性过滤器的语法与ogrsqlselect语句中的WHERE子句相同。所以这里关于WHERE子句的所有内容都适用于 SetAttributeFilter() 方法。

SELECT

SELECT语句用于获取层特征(类似于RDBMS中的表行),查询结果表示为临时特征层。数据源的层类似于RDBMS中的表,特征属性类似于列值。OGR SQL SELECT语句的最简单形式如下所示:

SELECT * FROM polylayer

在这种情况下,将从名为“polylayer”的图层获取所有特征,并返回这些特征的所有属性。这本质上相当于直接访问层。在这个例子中 是要从层中提取的字段列表,其中 “这意味着所有字段都应该被获取。

这个稍微复杂一点的表单仍然从层中提取所有特征,但是模式将只包含geometry列、EASu ID和PROPu VALUE属性。使用OGR SQL方言,geometry列总是包含在结果中,因此它不需要出现在SQL语句中。

SELECT eas_id, prop_value FROM polylayer

一个更加雄心勃勃的选择,限制用WHERE子句获取的特性,并对结果进行排序,可能如下所示:

SELECT * from polylayer WHERE prop_value > 220000.0 ORDER BY prop_value DESC

这个select语句将生成一个只有一个特征的表,其中包含几何图形和一个属性(命名为“countu easu id”之类的东西),该属性包含easu id属性的不同值的数目。

SELECT COUNT(DISTINCT eas_id) FROM polylayer

一般语法

SELECT语句的一般语法是:

SELECT [fields] FROM layer_name [JOIN ...] [WHERE ...] [ORDER BY ...] [LIMIT ...] [OFFSET ...]

列表运算符

字段列表是要从源层携带到输出要素中的字段的逗号分隔列表。它们将按照它们在字段列表中的显示顺序显示在输出要素上,因此可以使用字段列表对字段重新排序。

字段列表的特殊形式使用DISTINCT关键字。这将返回命名属性的所有不同值的列表。使用DISTINCT关键字时,字段列表中只能显示一个属性。DISTINCT关键字可用于任何类型的字段。目前,OGR-SQL中针对字符串值的区分性测试是不区分大小写的。带有DISTINCT关键字的SELECT的结果是一个具有一列(名称与操作的字段相同)和每个DISTINCT值一个特征的层。几何图形被丢弃。不同的值被组装在内存中,因此大量内存可用于具有大量不同值的数据集。

SELECT DISTINCT areacode FROM polylayer

还有一些汇总运算符可以应用于列。当摘要运算符应用于任何字段时,则所有字段都必须应用摘要运算符。摘要运算符包括COUNT(实例计数)、AVG(数值平均)、SUM(数值和)、MIN(词法或数值最小值)和MAX(词法或数值最大值)。此示例生成有关地块特性值的各种汇总信息:

SELECT MIN(prop_value), MAX(prop_value), AVG(prop_value), SUM(prop_value),
    COUNT(prop_value) FROM polylayer WHERE prov_name = 'Ontario'

还可以将COUNT()运算符应用于非重复选择以获取非重复值的计数,例如:

SELECT COUNT(DISTINCT areacode) FROM polylayer

作为一种特殊情况,COUNT()运算符可以被赋予一个“*”参数,而不是字段名,字段名是COUNT all records的缩写形式。

SELECT COUNT(*) FROM polylayer

字段名也可以以表名作为前缀,但这只有在执行联接时才真正有意义。它在JOIN部分进一步演示。

字段定义也可以是使用算术和函数运算符的复杂表达式。但是,DISTINCT关键字和摘要运算符(如MIN、MAX、AVG和SUM)可能不会应用于表达式字段。也可以使用布尔结果表达式(比较、逻辑运算符)。

SELECT cost+tax from invoice

SELECT CONCAT(owner_first_name,' ',owner_last_name) from properties

功能

SUBSTR函数可用于从字符串中提取子字符串。它的起始字符串(SUBSTR,语法如下 [,长度] ). 它提取string_expr的子字符串,从offset start_offset开始(1是string_expr的第一个字符,2是第二个字符,等等…)。如果start_offset为负值,则从字符串末尾提取子字符串(-1是字符串的最后一个字符,-2是最后一个字符之前的字符,…)。如果指定了长度,则从字符串中提取最长的字符。否则将提取字符串的其余部分。

注:目前,该字符被认为等同于字节,这可能不适用于多字节编码,如UTF-8。

SELECT SUBSTR('abcdef',1,2) FROM xxx   --> 'ab'
SELECT SUBSTR('abcdef',4)   FROM xxx   --> 'def'
SELECT SUBSTR('abcdef',-2)  FROM xxx   --> 'ef'

这个 hstore_get_value() 函数可用于从HSTORE字符串中提取与键关联的值,格式类似“key=>value,other_key=>other_value,…”

SELECT hstore_get_value('a => b, "key with space"=> "value with space"', 'key with space') FROM xxx --> 'value with space'

使用字段名别名

OGR SQL支持根据以下示例使用AS关键字重命名遵循SQL92规范的字段:

SELECT *, OGR_STYLE AS STYLE FROM polylayer

字段名别名可以用作列规范中的最后一个操作。因此,我们不能重命名运算符中的字段,但可以重命名整列表达式,如下所示:

SELECT COUNT(areacode) AS "count" FROM polylayer
SELECT dollars/100.0 AS cents FROM polylayer

更改字段的类型

OGR SQL支持根据以下示例使用符合SQL92的CAST运算符更改列的类型:

SELECT *, CAST(OGR_STYLE AS character(255)) FROM rivers

当前支持强制转换为以下目标类型:

  • 布尔

  • 字符(字段长度)。默认情况下,字段长度=1。

  • 浮动(字段长度)

  • 数值(字段长度,字段精度)

  • smallint(字段长度):16位有符号整数

  • 整数(字段长度)

  • bigint(字段长度),64位整数,扩展到SQL92

  • 日期(字段长度)

  • 时间(字段长度)

  • 时间戳(字段长度)

  • 几何学,几何学(几何学类型),几何学(几何学类型,epsg代码)

指定字段长度和/或字段精度是可选的。显式值为零可以用作character()的宽度,以指示可变宽度。不支持转换为“integer list”、“double list”和“string list”OGR数据类型,这不符合SQL92规范。

虽然CAST运算符可以应用于表达式中的任何位置,包括在WHERE子句中,但只有当CAST运算符是字段定义列表中字段的“最外层”运算符时,才支持对输出字段格式的详细控制。在其他上下文中,在数字、字符串和日期数据类型之间进行转换仍然很有用。

允许将WKT字符串转换为几何体。几何图形类型可以是点 [Z] ,线条字符串 [Z] ,多边形 [Z] ,多点 [Z] ,多行 [Z] ,多多边形 [Z] ,几何集合 [Z] 或几何学 [Z] .

字符串文字和标识符引用

严格的SQL92规则适用于字符串文字和标识符引用。

字符串文本(常量)必须用单引号字符包围。e、 g.其中a_字段=a_值

如果标识符(列名和表名)不包含特殊字符或不是SQL保留关键字,则可以使用不带引号的标识符。否则它们必须用双引号字符包围。e、 g.其中“from”=5。

WHERE

WHERE子句的参数是一个逻辑表达式,用于从源层选择记录。除了在WHERE语句中使用之外,WHERE子句处理还用于通过 OGRLayer::SetAttributeFilter() .

除了SELECT语句的field selection子句中的表达式中可用的算术运算符和其他函数运算符外,WHERE上下文中还可用逻辑运算符,表达式的计算值应为逻辑值(true或false)。

可用的逻辑运算符有 =!=<><><=>=LIKEILIKEBETWEENIN . 大多数运算符都是不言而喻的,但值得注意的是 != 是一样的 <> ,字符串相等不区分大小写,但是 <><=>= 算子 are 区分大小写。

从gdal3.1开始,LIKE区分大小写,而ILIKE不区分大小写。在以前的版本中,LIKE也不区分大小写。如果GDAL3.1中希望使用旧行为,则 OGR_SQL_LIKE_AS_ILIKE 可以设置为 YES .

的值参数 LIKEILIKE 运算符是与值字符串匹配的模式。在此模式中,百分比(%)匹配任意数量的字符,下划线(u)匹配任意一个字符。可以添加可选的ESCAPE ESCAPE_char子句,以便通过在前面加ESCAPE_char,可以将百分比或下划线字符作为常规字符进行搜索。

String             Pattern       Matches?
------             -------       --------
Alberta            ALB%          Yes
Alberta            _lberta       Yes
St. Alberta        _lberta       No
St. Alberta        %lberta       Yes
Robarts St.        %Robarts%     Yes
12345              123%45        Yes
123.45             12?45         No
N0N 1P0            %N0N%         Yes
L4C 5E2            %N0N%         No

这个 IN 将值列表作为其参数,并测试所提供集的成员身份的属性值。

Value              Value Set            Matches?
------             -------              --------
321                IN (456,123)         No
'Ontario'          IN ('Ontario','BC')  Yes
'Ont'              IN ('Ontario','BC')  No
1                  IN (0,2,4,6)         No

的语法 BETWEEN 运算符是“field_name BETWEEN value1 AND value2”,相当于“field_name>=value1 AND field_name<=value2”。

除了上述二进制运算符之外,还有其他运算符用于测试字段是否为空。这些是 IS NULLIS NOT NULL 操作员。

可以使用逻辑运算符将基本字段测试组合到更复杂的谓词中,包括 ANDOR ,一元逻辑 NOT . 子表达式应放在括号中,以明确优先级。一些更复杂的谓词是:

SELECT * FROM poly WHERE (prop_value >= 100000) AND (prop_value < 200000)
SELECT * FROM poly WHERE NOT (area_code LIKE 'N0N%')
SELECT * FROM poly WHERE (prop_value IS NOT NULL) AND (prop_value < 100000)

限制条件

  • 字段必须全部来自主表(from子句中列出的表)。

  • 所有字符串比较都不区分大小写,除了 <><=>=

订货人

这个 ORDER BY 子句用于强制将返回的特性重新排序为一个或多个字段的排序顺序(升序或降序)。如果未提供ASC或DESC关键字,则默认为升序(递增)。例如:

SELECT * FROM property WHERE class_code = 7 ORDER BY prop_value DESC
SELECT * FROM property ORDER BY prop_value
SELECT * FROM property ORDER BY prop_value ASC
SELECT DISTINCT zip_code FROM property ORDER BY zip_code
SELECT * FROM property ORDER BY prop_value ASC, another_field DESC

注意ORDER BY子句会导致两次通过特性集。一个用于构建与特征id对应的字段值的内存表,另一个用于按特征id按排序顺序获取特征。对于不能通过特征id有效地随机读取特征的格式,这可能是一个非常昂贵的操作。

字符串字段值的排序是区分大小写的,不像OGR SQL的大多数其他部分那样不区分大小写。

限制和偏移

从GDAL 2.2开始 LIMIT 子句可用于限制返回的功能数。例如

SELECT * FROM poly LIMIT 5

这个 OFFSET 子句可用于跳过结果集的第一个功能。偏移后的值是跳过的特征数。例如,要从结果集中跳过前3个功能:

SELECT * FROM poly OFFSET 3

这两个条款可以组合在一起:

SELECT * FROM poly LIMIT 5 OFFSET 3

JOINs

OGR SQL支持一对一连接的有限形式。这允许根据次表与查询的主表之间的共享键查找次表中的记录。例如,城市位置表可能包括 nation_id 可以用作辅助对象的引用的列 国家 获取国家名称的表。连接的查询可能如下所示:

SELECT city.*, nation.name FROM city
    LEFT JOIN nation ON city.nation_id = nation.id

此查询将生成一个包含city表中所有字段的表,并通过在nation表中查找具有与city.nationu id字段值相同的“id”字段的记录,生成一个附加的“nation.name”字段,其中包含从nation表中提取的nation名称。

Joins引入了一些额外的问题。一个是字段名上的表限定符的概念。例如,引用city.nation_id而不是仅引用nation_id来指示来自city层的nation_id字段。表名限定符只能在字段列表中使用,并且在 ON 连接的子句。

通配符也更为复杂。主表中的所有字段( city 在这种情况下)和二级表( 国家 在这种情况下)可以使用通常的 * 通配符。但是,只有一个主表或辅助表的字段可以通过在星号前加上表名来选择。

如果表名在字段列表中作为限定符给定,则结果查询层中的字段名将由表名限定。此外,如果字段名与前面的字段冲突,则将使用表名进行限定。例如,下面的select可能会导致 name, nation_id, nation.nation_idnation.name 如果城市和国家的桌子都有 nation_idname 字段名。

SELECT * FROM city LEFT JOIN nation ON city.nation_id = nation.nation_id

另一方面,如果国家议席上 continent_id 字段,但city表没有,则该字段不需要在结果集中进行限定。但是,如果所选内容看起来像下面的语句,则所有结果字段都将由表名限定。

SELECT city.*, nation.* FROM city
    LEFT JOIN nation ON city.nation_id = nation.nation_id

在上面的例子中 国家 在与 city 桌子。但是,OGR连接支持包括对不同数据源(可能是不同格式)中的表进行连接的能力。这是通过将辅助表名限定为数据源名来表示的。在这种情况下,使用普通的OGR语义打开辅助数据源,并用于访问辅助表,直到不再需要查询结果为止。

SELECT * FROM city
LEFT JOIN '/usr2/data/nation.dbf'.nation ON city.nation_id = nation.nation_id

虽然不一定非常有用,但是也可以引入表别名来简化一些SELECT语句。这对于消除使用来自不同数据源的同名表的情况也很有用。例如,如果实际的表名很乱,我们可能需要执行以下操作:

SELECT c.name, n.name FROM project_615_city c
LEFT JOIN '/usr2/data/project_615_nation.dbf'.project_615_nation n
            ON c.nation_id = n.nation_id

可以在一个查询中执行多个联接。

SELECT city.name, prov.name, nation.name FROM city
LEFT JOIN province ON city.prov_id = province.id
LEFT JOIN nation ON city.nation_id = nation.id

ON之后的表达式通常采用“{primaryu table}.{fieldu name}={secondaryu table}.{fieldu name}”的形式,并按此顺序排列。也可以使用更复杂的布尔表达式,它涉及多个比较运算符,但有下面“连接限制”部分中提到的限制。特别是,在多个联接(3个或更多表)的情况下,联接中比较的字段必须属于主表(FROM之后的表)和活动联接的表。

连接限制

  • 如果在使用的键字段上没有索引辅助表,则联接可能是非常昂贵的操作。

  • 此时,在WHERE子句或ORDER BY子句中不能使用联接字段。在所有主表子集设置完成之后,以及在ORDER BY pass之后,连接本质上是求值的。

  • 在以后的联接中,联接字段不能用作键。因此,您不能使用城市中的省标识来查找省记录,然后使用省标识中的国家标识来查找国家记录。这是一个明智的想法,可以实现,但目前不受支持。

  • 关联表的数据源名称是相对于当前进程工作目录而不是主数据源的路径计算的。

  • 在RDBMS意义上,这不是真正的左连接或右连接。无论联接键是否存在辅助记录,结果集中都只返回一个主记录副本。如果找不到辅助记录,则辅助派生字段将为空。如果找到多个匹配的辅助字段,则只使用第一个。

全部联合

SQL引擎可以处理多个SELECT和UNION ALL的组合。UNION ALL的作用是将right SELECT语句返回的行连接到left SELECT语句返回的行。

[(] SELECT field_list FROM first_layer [WHERE where_expr] [)]
UNION ALL [(] SELECT field_list FROM second_layer [WHERE where_expr] [)]
[UNION ALL [(] SELECT field_list FROM third_layer [WHERE where_expr] [)]]*

联合所有限制

OGR中UNION ALL的处理不同于SQL标准,它接受来自不同SELECT的列不相同。在这种情况下,它将返回每个SELECT语句中所有字段的超级集。

还有一个限制:只能为每个SELECT指定ORDER BY,不能在union的结果级别指定ORDER BY。

特殊领域

OGR SQL查询处理器将特性的某些属性视为内置的特殊字段,可以在SQL语句中使用,与其他字段类似。这些字段可以分别放在select列表、WHERE子句和ORDER BY子句中。默认情况下,特殊字段不会包含在结果中,但可以通过将其添加到“选择”列表来显式包含它。访问字段值时,特殊字段将优先于数据源中具有相同名称的其他字段。

FID

通常,特征id是特征的一个特殊属性,不作为特征的属性处理。在某些情况下,可以方便地将查询和结果集中的特征id用作常规字段。为此,请使用名称 FID . 字段通配符扩展将不包括功能id,但可以使用如下语法显式包括它:

SELECT FID, * FROM nation

几何字段

默认情况下,ogrsql方言将数据源的geometry字段添加到结果集。用户不需要显式选择几何图形,但仍然可以这样做。常见的用例是当几何体是唯一需要的字段时。在本例中,要在SQL语句中使用的几何体字段的名称是 OGRLayer::GetGeometryColumn() . 如果该方法返回空字符串,则必须使用特殊名称“u ogru geometry”。名称以下划线开头,SQL语法要求它必须出现在双引号之间。此外,命令行解释器可能要求双引号转义,并且最终SELECT语句可能如下所示:

SELECT "_ogr_geometry_" FROM nation

OGR_GEOMETRY

一些数据源(如MapInfo tab)可以处理同一层中不同类型的几何图形。这个 OGR_GEOMETRY 特殊字段表示返回的几何体类型 OGRGeometry::getGeometryName() 可以用来区分各种类型。通过使用此字段,可以选择特定类型的几何图形,如:

SELECT * FROM nation WHERE OGR_GEOMETRY='POINT' OR OGR_GEOMETRY='POLYGON'

OGR_GEOM_WKT

几何图形的已知文本表示也可以用作特殊字段。选择几何图形的WKT OGR_GEOM_WKT 可能包含在“选择”列表中,例如:

SELECT OGR_GEOM_WKT, * FROM nation

使用 OGR_GEOM_WKT 以及 LIKE WHERE子句中的运算符我们可以获得与使用OGR_几何体类似的效果:

SELECT OGR_GEOM_WKT, * FROM nation WHERE OGR_GEOM_WKT
LIKE 'POINT%' OR OGR_GEOM_WKT LIKE 'POLYGON%'

OGR_GEOM_AREA

这个 OGR_GEOM_AREA 特殊字段返回由OGRSurface::get_area()方法计算的特征几何图形的面积。对于ogrgometrycollection和OGRMultiPolygon,该值是其成员区域的总和。对于非曲面几何图形,返回区域为0.0。

例如,要仅选择大于给定区域的多边形要素:

SELECT * FROM nation WHERE OGR_GEOM_AREA > 10000000

OGR_STYLE

这个 OGR_STYLE 特殊字段表示OGRFeature::GetStyleString()返回的功能的样式字符串。通过使用此字段和 LIKE 运算符可以按样式筛选查询结果。例如,我们可以将注释要素选择为:

SELECT * FROM nation WHERE OGR_STYLE LIKE 'LABEL%'

创建索引

一些OGR SQL驱动程序支持创建属性索引。目前这包括Shapefile驱动程序。索引可以加速表单的非常简单的属性查询 fieldname = value ,这就是 JOIN 能力。要在nation表的nationu id字段上创建属性索引,将使用如下命令:

CREATE INDEX ON nation USING nation_id

索引限制

  • 将新功能添加到图层或从图层中删除时,不会动态维护索引。

  • 非常长的字符串(超过256个字符?)当前无法编制索引。

  • 要重新创建索引,必须删除层上的所有索引,然后重新创建所有索引。

  • 索引不用于任何复杂查询。目前唯一会加速的查询是一个简单的“field=value”查询。

删除索引

OGR SQL DROP INDEX命令可用于删除特定表上的所有索引,或仅删除特定列的索引。

DROP INDEX ON nation USING nation_id
DROP INDEX ON nation

更改表

可以使用以下OGR SQL ALTER TABLE命令。

-“更改表tablename ADD [COLUMN] columnname columntype“添加新字段。如果层声明OLCCreateField功能,则支持。-“更改表tablename RENAME [COLUMN] oldcolumnname TO newcolumnname“重命名现有字段。如果层声明OLCAlterFieldDefn功能,则支持。-“更改表tablename ALTER [COLUMN] columnname TYPE columntype“更改现有字段的类型。如果层声明OLCAlterFieldDefn功能,则支持。-“更改表tablename DROP [COLUMN] columnname“删除现有字段。如果层声明OLCDeleteField功能,则支持。

columntype值遵循上述CAST运算符支持的类型的语法。

ALTER TABLE nation ADD COLUMN myfield integer
ALTER TABLE nation RENAME COLUMN myfield TO myfield2
ALTER TABLE nation ALTER COLUMN myfield2 TYPE character(15)
ALTER TABLE nation DROP COLUMN myfield2

升降台

OGR SQL DROP TABLE命令可用于删除表。这仅在声明ODsCDeleteLayer功能的数据源上受支持。

DROP TABLE nation

执行SQL()

SQL是针对GDALDataset执行的,而不是针对特定的层。电话是这样的:

OGRLayer * GDALDataset::ExecuteSQL( const char *pszSQLCommand,
                                    OGRGeometry *poSpatialFilter,
                                    const char *pszDialect );

这个 pszDialect 参数在理论上是为了允许对提供程序支持不同的命令语言,但目前应用程序应始终传递空(非空)字符串以获取默认方言。

这个 poSpatialFilter 参数是一种几何图形,用于选择要以类似于 OGRLayer::SetSpatialFilter() 方法。由于没有特殊的空间限制,它可能为空。

ExecuteSQL()调用的结果通常是表示语句结果集的临时OGRLayer。例如,SELECT语句就是这样。返回的临时层应使用 GDALDataset::ReleaseResultsSet() 方法时不再需要。在数据源被销毁之前未能释放它可能会导致崩溃。

非OGR SQL

All OGR drivers for database systems: MySQL, PostgreSQL/邮政地理信息系统, 空间数据库, SQLite/spacealite关系数据库管理系统, ODBC关系数据库, ESRI个人地理数据库, SAP HANA and MSSQLSpatial-Microsoft SQL Server空间数据库, override the GDALDataset::ExecuteSQL() function with dedicated implementation and, by default, pass the SQL statements directly to the underlying RDBMS. In these cases the SQL syntax varies in some particulars from OGR SQL. Also, anything possible in SQL can then be accomplished for these particular databases. Only the result of SQL WHERE statements will be returned as layers.