结构化查询语言 (SQL) 是一种标准计算机语言,其中包含一组定义的语法和表达式,用于访问和管理数据库以及其他数据处理技术中的数据。美国国家标准学会 (ANSI) 定义 SQL 的标准。 大多数关系数据库管理系统 (RDBMS) 使用并扩展了该标准,因此不同 RDBMS 之间的 SQL 语法都略有不同。ArcGIS 中的查询表达式遵循标准 SQL 表达式。 表达式中所使用的 SQL 语法因数据源的不同而有所差异。 每个数据源都有其自己的 SQL 变体,称为 SQL 方言,如下所示:基于文件的数据(包括文件地理数据库、shapefile、内存型表视图、文本文件(如 .dbf、.csv、.txt、.xlsx 表)和使用标准化查询的要素服务)使用支持 SQL 功能子集的 ArcGIS SQL 方言。移动地理数据库 ST_geometry SQLite、Open Geospatial Consortium (OGC) GeoPackage 和 Microsoft Excel 使用 SQLite SQL 方言。数据库和企业级地理数据库使用基础 RDBMS 的 SQL 语法,例如,Oracle、Microsoft SQL Server、PostgreSQL、SAP HANA 和 IBM Db2,其中各数据库使用其各自略有不同的 SQL 方言。使用 ArcGIS 对话框构建 SQL 表达式时,将使用自动完成功能来帮助您为查询的数据源应用正确的语法。 在您输入时会显示一条提示信息,显示您的数据源支持的字段名称、值、关键字和运算符。在 ArcGIS Pro 中,可以在以下位置找到 SQL 表达式对话框:使用按属性选择图层地理处理工具按属性选择。图层属性对话框上的定义查询选项卡。符号系统窗格中的显示过滤器选项卡。使用创建新报表窗格创建报表。使用导出表地理处理工具导出表。使用导出要素地理处理工具导出要素。使用计算字段地理处理工具创建表达式,以对字段值执行简单或复杂的计算。使用选择查询数据以进行进一步分析。使用创建查询表地理处理工具创建图层或表视图。使用创建要素图层地理处理工具创建要素图层。使用创建数据库视图地理处理工具在数据库或地理数据库中创建视图。使用追加地理处理工具将多个输入数据集追加到目标数据集中。使用 ProSDK Core.Data.QueryDef。
SQL 表达式语法SQL 表达式包含一个或多个值、运算符和 SQL 函数的组合,可用于在 ArcGIS 中查询或选择要素和表记录的子集。所有 SQL 查询均使用关键字 SELECT 表示。 SELECT * FROM 构成 SQL 表达式的第一部分,并在大多数 ArcGIS 对话框中自动为您提供。 例如,当您通过编写 SQL 语法构造查询时,将使用 SELECT 语句从图层或表中选择字段,并为您提供该语句。SELECT * FROM <Layer_name> 之后的 SQL 表达式的下一部分是 WHERE 子句。 WHERE 子句用于获取满足特定条件的记录,并且它是您必须构建的表达式的一部分。这是 SQL 表达式 WHERE 子句的基本形式:<Field_name> <Operator> <Value or String>例如,STATE_NAME = 'Florida'。 该表达式包含一个子句,并在 STATE_NAME 字段中选择所有包含 'Florida' 的要素。对于复合表达式,使用以下形式: <Field_name> <Operator> <Value or String> <Connector> <Field_name> <Operator> <Value or String> ... 例如,STATE_NAME = 'Florida' OR (STATE_NAME = 'South Carolina' AND POP2010 > 15000)。 该复合表达式由逻辑运算符 AND 或 OR 连接的多个子句组成,用于选择 STATE_NAME 字段中包含 Florida 的所有要素,以及 STATE_NAME 字段中包含 South Carolina 且名为 POP2010 字段中包含的值大于 15,000 的所有要素。因为选择列作为一个整体,所以不能限制 SELECT 语句仅返回对应表中的某些列,因为 SELECT * 语法是硬编码的。 因此,除非使用子查询,否则不能在 ArcGIS 的 SQL 表达式中使用 DISTINCT、ORDER BY 和 GROUP BY 等关键字。 有关详细信息,请参阅以下子查询部分。以下各部分描述了 ArcGIS 中使用的常见 SQL 查询表达式的元素。常见查询:搜索字符串查询中的字符串必须始终用单引号括起,例如:STATE_NAME = 'California'表达式中的字符串区分大小写,但在 Microsoft SQL Server 中针对地理数据库运行时除外。 要在其他数据源中进行步区分大小写的搜索,可使用 SQL 函数将所有值转换为相同的大小写形式。 对于基于文件的数据源(例如文件地理数据库或 shapefile),可使用 UPPER 或 LOWER 函数设置选择的大小写形式。 例如,以下表达式将选择名称存储为“Rhode Island”或“RHODE ISLAND”的州:UPPER(STATE_NAME) = 'RHODE ISLAND'可以使用 LIKE 运算符(而非 = 运算符)来构建部分字符串搜索。 例如,以下表达式将从美国州名称中选择 Mississippi 和 Missouri:STATE_NAME LIKE 'Miss%'使用 IN 运算符指定多个值。 例如,选择加利福尼亚、纽约和科罗拉多中的所有值。STATE_NAME IN ('California', 'New York', 'Colorado')如果字符串包含单引号,您首先需要使用另一单引号作为转义字符,例如:NAME = 'Alfie''s Trough' OWNER_NAME IN ('Joseph D''Souza', 'Katherine Smith', 'Tim O''Brien')百分号 (%) 表示这个位置可以是任意字符,即 1 个字符、100 个字符或者无字符均可。 此外,要在查询时通配符仅代表一个字符,可使用下划线 (_)。 例如,以下表达式将找到 Catherine Smith 和 Katherine Smith:OWNER_NAME LIKE '_atherine Smith'还可使用大于 (>)、小于 (<)、大于等于 (>=)、小于等于 (<=)、不等于 (<>) 以及 BETWEEN 运算符来基于排序顺序选择字符串值。 例如,以下表达式将选择 coverage 中名称首字母为 M 到 Z 的所有城市:CITY_NAME >= 'M'字符串函数可用来格式化字符串。 例如,LEFT 函数将返回字符串左侧特定数量的字符。 在以下示例中,查询将返回以字母 A 开头的所有州:LEFT(STATE_NAME,1) = 'A'有关支持的函数列表,请参阅 RDBMS 文档。常见表达式:搜索空值可以使用 NULL 关键字选择要素并记录指定字段的值为空。 NULL 关键字的前面始终为 IS 或 IS NOT。 例如,要查找尚未输入 1996 年人口的城市,可使用以下表达式:POPULATION IS NULL或者,要查找已输入 1996 年人口的城市,可使用以下表达式:POPULATION96 IS NOT NULL如果已选择几何字段,则仅可以搜索 NULL 和 NOT NULL 关键字。常见表达式:搜索数值无论您的区域设置如何,小数点 (.) 将始终用作小数分隔符。 在表达式中不能使用逗号作为小数分隔符或千位分隔符。可以使用等于 (=)、不等于 (<>)、大于 (>)、小于 (<)、大于等于 (>=)、小于等于 (<=) 和 BETWEEN 运算符查询数值,例如:POPULATION >= 5000数值函数可用来格式化数值。 例如,ROUND 函数可将文件地理数据库中的数值四舍五入到指定的小数位数:ROUND(SQKM,0) = 500有关支持的数值函数列表,请参阅 RDBMS 文档。日期和时间通用规则和常见表达式地理数据库数据源在日期时间字段中存储日期。 但是,shapefile 并非如此。 因此,下面所列的大部分查询语法都包含对时间的引用。 在某些情况下,当已知字段只包含日期时,查询中的时间部分可以安全地省略掉;而在其他情况下则需要声明,否则查询将返回语法错误。要搜索日期字段,需要注意日期时间字段的类型以及数据源所需的语法。 如果在查询构建器的“子句”模式下构建日期查询,将自动为用户生成正确的语法。 下面是一个查询示例,它将返回文件地理数据库数据源的日期时间字段中 2011 年 1 月 1 日或之后的所有记录。INCIDENT_DATE >= timestamp '2011-01-01 00:00:00'当非空时间带日期存储时(例如 1999 年 1 月 12 日 04:00:00),查询仅日期时不会返回记录。 如果将仅日期传递至日期时间字段,则会在时间中填充零,并仅检索时间为上午 12:00:00 的记录。属性表内会以用户友好的格式来显示日期和时间(取决于用户的区域设置)而不是采用基础数据库的格式。 这可能存在一些缺点:SQL 查询中显示的字符串可能会与表中显示的值稍有不同,尤其是当包含时间时。 例如,输入的时间 00:00:15 将在属性表中(当您的区域设置为美国时)显示为 12:00:15 a.m.,对应于查询语法将是 Datefield = '1899-12-30 00:00:15'。属性表在您保存编辑之前无法知道是何种基础数据源。 它首先会尝试将输入的值格式化为符合自己的格式,然后在保存编辑内容时,会再尝试对生成的值进行调整以便存入数据库。 因此,您可以在 shapefile 中输入一个时间值,但您会发现当您保存编辑内容时该值会被丢弃。 随后该字段将包含值“1899-12-30”并显示 12:00:00 a.m. 或其他等效的值(取决于您的区域设置)。地理数据库的日期时间语法下面是文件地理数据库、移动地理数据库和 shapefile 中的日期支持的日期时间 SQL 语法的示例。 一些企业级地理数据库和 RDBMS 数据源还支持日期时间 SQL 语法,尽管这些数据源可能需要稍微不同的 SQL 语法。有关支持的特定 SQL 表达式语法和数据类型,请查阅适用于您的数据库管理系统的文档。文件地理数据库文件地理数据库中的仅日期和仅时间字段分别前置 date 或 time 一词。 日期时间字段前置 timestamp。Datefield = timestamp 'yyyy-mm-dd'文件地理数据库支持在日期字段中使用时间,因此可将此加入到表达式中:Datefield = timestamp 'yyyy-mm-dd hh:mm:ss'对于仅日期、仅时间或带偏移的时间戳字段,使用以下格式://DateOnlyField = time 'yyyy-mm-dd'
DateOnlyField = time '2003-01-08'
//TimeOnlyField = date 'HH24:mm:ss'
TimeOnlyField = date '14:35:00'
//TimestampOffsetField = timestamp 'yyyy-mm-dd HH24:mm:ss -TZH:TZM'
TimestampOffsetField = timestamp '2003-01-08 14:35:00 -08:00'移动地理数据库某些类型的日期字段前置 JULIANDAY 一词。 其他字段未使用函数进行语法格式化。Datefield = JULIANDAY('yyyy-mm-dd')移动地理数据库支持在日期字段中使用时间,因此可将此加入到表达式中:Datefield = JULIANDAY('yyyy-mm-dd HH24:mm:ss')//TimestampOffsetField = 'yyyy-mm-dd HH24:mm:ss -TZH:TZM'
TimestampOffsetField = '2003-01-08 14:35:00 -08:00'
//DateOnlyField = JULIANDAY('yyyy-mm-dd')
DateOnlyField = JULIANDAY('2003-01-08')
//TimeOnlyField = 'HH24:mm:ss'
TimeOnlyField = '14:35:00'shapefile、coverage 和其他基于文件的数据源shapefile 中的日期前面要加上 date 一词。Datefield = date 'yyyy-mm-dd'shapefile 和 coverage 不支持在日期字段中使用时间。已知局限性对连接的左侧部分(第一张表)的日期查询只适用于基于文件的数据源,如文件地理数据库、shapefile 和 DBF 表。 不过,对于非基于文件的数据(如企业级地理数据库数据)也有解决方法,如下文所述。当使用为基于文件的数据源所开发的受限的 SQL 版本时,对连接的左侧部分的日期查询将获得成功。 如果您没有使用此类数据源,可以强制表达式使用这种格式。 您可以通过确保查询表达式涉及一个以上连接表的字段来实现此操作。 例如,如果要素类和表(FC1 和 Table1)进行连接且均来自于企业级地理数据库,则下列表达式将失败或不返回任何数据:FC1.date = date #01/12/2001#
FC1.date = date '01/12/2001'要想查询成功,您可以创建如下查询:FC1.date = date '01/12/2001' and Table1.OBJECTID > 0由于此查询涉及到两个表的字段,因此将使用受限的 SQL 版本。 在此表达式中,连接创建期间匹配记录的 Table1.OBJECTID 始终为 > 0,因此对于包含连接匹配项的所有行来说此表达式均为 true。要确保选择 FC1.date = date '01/12/2001' 的每条记录,可使用下列查询:FC1.date = date '01/12/2001' and (Table1.OBJECTID IS NOT NULL OR Table1.OBJECTID IS NULL)此查询将选择 FC1.date = date '01/12/2001' 的所有记录,而无论每条记录是否是连接匹配项。组合表达式通过使用 AND 和 OR 运算符将表达式组合在一起,可构建复合表达式。 例如,以下表达式将选择面积超过 1,500 平方英尺的所有房屋和一个可容纳三台或更多汽车的车库。AREA > 1500 AND GARAGE > 3如果使用 OR 运算符,OR 运算符两侧的两个表达式中必须至少有一个为真时才会选择记录,例如:RAINFALL < 20 OR SLOPE > 35在表达式开头使用 NOT 运算符可查找与指定表达式不匹配的要素或记录,例如:NOT STATE_NAME = 'Colorado'NOT 表达式可与 AND 和 OR 运算符相结合。 例如,以下表达式将选择除 Maine 以外的所有新英格兰州:SUB_REGION = 'New England' AND NOT STATE_NAME = 'Maine'
计算可使用算术运算符 +、-、* 和 / 在查询中加入计算: 可在字段和数字之间进行计算,例如:AREA >= PERIMETER * 100也可在字段之间进行计算。 例如,要查找人口密度小于等于每平方英里 25 人的所有国家,可使用以下表达式:POP1990 / AREA <= 25运算符优先级表达式求值顺序遵照标准的运算符优先级规则。 例如,求值时,首先计算括号内部的表达式部分,然后再计算其他部分。HOUSEHOLDS > MALES * (POP90_SQMI + AREA)当编辑 SQL 表达式时,可以通过输入括号的方式在 SQL 编辑模式下添加括号,也可以在“子句”模式下使用分组或取消分组命令添加或移除括号。 子查询子查询是嵌套在另一个查询中的查询,仅受地理数据库数据源支持。 子查询可用于应用谓词或聚合函数,或将数据与存储在另一张表中的值进行比较。 可使用 IN 或 ANY 关键字来执行此操作。 例如,以下查询只会选择未在 indep_countries 表中列出的国家:COUNTRY_NAME NOT IN (SELECT COUNTRY_NAME FROM indep_countries)此查询将返回国家中 GDP2006 大于 GDP2005 的所有要素:GDP2006 > (SELECT MAX(GDP2005) FROM countries)文件地理数据库仅提供对以下子查询的支持:
包含比较运算符的标量子查询。 标量子查询返回单个值,例如:GDP2006 > (SELECT MAX(GDP2005) FROM countries)对于文件地理数据库,集合函数 AVG、COUNT、MIN、MAX 和 SUM 只能用在标量子查询内。EXISTS 谓词,例如:EXISTS (SELECT * FROM indep_countries WHERE COUNTRY_NAME = 'Mexico')运算符以下是文件地理数据库、shapefile、coverage 和其他基于文件的数据源所支持的查询运算符的完整列表。 企业级地理数据库也支持这些运算符,但这些数据源可能使用不同的语法。 除了以下这些运算符外,企业级地理数据库还支持一些其他功能。 有关详细信息,请参阅 RDBMS 文档。算术运算符算术运算符用于对数值进行加、减、乘、除的运算。比较运算符使用比较运算符可以将两个表达式进行比较。逻辑运算符与比较运算符类似,逻辑运算符会测试语句的真实性并返回适用于给定语句的值。字符串运算符函数以下是文件地理数据库、shapefile、coverage 和其他基于文件的数据源所支持的函数的完整列表。 企业级地理数据库也支持这些函数,但这些数据源可能需要不同的语法或函数名。 除了以下这些函数外,企业级地理数据库还支持一些其他功能。 有关详细信息,请参阅 RDBMS 文档。日期函数所有日期函数都将返回一个日期值。文件地理数据库文件地理数据库的 EXTRACT 用法示例: EXTRACT(YEAR from DateOnly) > 1951EXTRACT(YEAR from DateTimestamp) > 1981EXTRACT(YEAR from TimestampOffset) > 1981EXTRACT(TIMEZONE_HOUR from timeStampOffset) > 3EXTRACT(TIMEZONE_MINUTE from timeStampOffset) = 30 移动地理数据库移动地理数据库的 EXTRACT 用法示例: EXTRACT('YEAR', DateOnly) > 1951 EXTRACT('YEAR', DateTimestamp) > 1981 EXTRACT('YEAR', TimestampOffset) > 1981 EXTRACT('TIMEZONE_HOUR', timeStampOffset) > 3 EXTRACT('TIMEZONE_MINUTE', timeStampOffset) = 30 了解有关日期和时间字段数据类型的详细信息字符串函数以 string_exp 表示的参数可以是列名、字符串文本或者另一个标量函数的结果,其基础数据类型可表示为字符型。以 character_exp 表示的参数是长度可变的字符型字符串。以 start 或 length 表示的参数可以是数值文本或者另一个标量函数的结果,其基础数据类型可表示为数值型。这些字符串函数以 1 为基础;即字符串的第一个字符为字符 1。数值函数所有数值函数均返回数值型值。以 numeric_exp、float_exp 或 integer_exp 表示的参数可以是列名、另一个标量函数的结果或数值文本,其基础数据类型可表示为数值型。CAST 函数CAST() 函数将值或表达式从一种数据类型转换为另一种指定的数据类型。 语法如下:CAST (expression AS data_type(length))其中 expression 是必填参数,可以是文本值或将要转换的任何类型(例如,列名、变量)的有效表达式。其中 data_type 是必填参数,使用的关键字是表达式将转换为的结果数据类型。 有关用于有效数据类型的关键字列表,请参阅下表。其中 length 是可选参数,用于指定结果数据类型的长度。例如,在某些方案中,可能需要字符串操作,但是如果数据存储在数值类型字段中,则查询将无法工作。 但是,可使用 CAST() 函数将数值字段转换为用于 SQL 操作的字符串。 此代码将数值字段 SQLNUM 强制转换为文本字段,然后可将其用于文本操作中。CAST(SQLNUM AS CHARACTER(12))下表包含用于数据类型转换的关键字,可以将其指定为大写或小写形式。使用 CAST 函数时支持的数据类型转换CAST 函数示例示例 1:CAST(AREA AS INTEGER)将 Float 数据类型的 AREA 转换为 INTEGER 会返回一个整数,并截断小数点后的任何结果值。 示例 2:CAST(Rent AS FLOAT) + Utilities > 2000.45将 CHARACTER 数据类型的 Rent 转换为 FLOAT 数据类型,其中 Utilities 也是 FLOAT 数据类型。EsriCastSQLite CAST 运算符用于处理原生数据类型;但是,随着新字段类型以及其他更多非原生数据类型的发布,您必须调整运算符,以使 SQLite 可以正确运行。 EsriCast 的开发是为了使移动地理数据库中必要的 SQLite 运算符能够访问和理解 ArcGIS Pro 可处理的多种数据类型。示例语法:EsriCast(expression, source_data_type, target_data_type)EsriCast 数据关键字EsriCast 数据转换示例
相关主题在查询构建器中编写查询构造和修改查询控制 SQL 查询中的运算顺序
有关此主题的反馈?