本主题将介绍 ArcGIS 中的选择表达式所用的常规查询的各个元素。ArcGIS 中的查询表达式使用常规 SQL 语法。
字段
在 SQL 表达式中指定字段时,如果该字段名可能产生岐义(比如与 SQL 保留关键字相同),则需提供一个分隔符。
由于存在许多保留关键字,并且后续版本中还能添加新的保留关键字,所以建议您始终使用分隔符将字段名称括起来。
DBMS 和 DBMS 之间的字段名分隔符有所不同。如果要查询任何基于文件的数据(例如,文件地理数据库、ArcSDE 地理数据库数据,或者 ArcIMS 要素类或影像服务子图层中的数据),可以将字段名称用双引号括起:
"AREA"
如果要查询个人地理数据库数据,可以将字段名称用方括号括起:
[AREA]
对于个人地理数据库栅格数据集,应将字段名称用双引号括起:
"AREA"
对于文件地理数据库数据,您可以将字段名称用双引号括起,但是通常不需要。
AREA
字符串
查询中的字符串必须始终用单引号括起。例如:
STATE_NAME = 'California'
- 表达式中的字符串区分大小写。对于要素类和表,可以用 UPPER 或 LOWER 函数设置所选项的大小写。例如:
UPPER(STATE_NAME) = 'RHODE ISLAND'
- 个人地理数据库要素类和表中的字符串不区分大小写。如果需要,可以使用与 UPPER 或 LOWER 等效的 UCASE 和 LCASE 函数。
- 如果字符串包含单引号,您首先需要使用另一单引号作为转义字符。例如:
NAME = 'Alfie''s Trough'
进行部分字符串搜索所用的通配符还取决于所要查询的数据源。例如,在基于文件的或 ArcSDE 地理数据库数据源中,以下表达式将从美国州名称中选择 Mississippi 和 Missouri:
STATE_NAME LIKE 'Miss%'
百分号 (%) 表示这个位置可以是任意字符,即 1 个字符、100 个字符或者无字符均可。查询个人地理数据库时,使用通配符星号 (*) 代表任意数量的字符,而使用问号 (?) 代表 一个字符。
字符串函数可用来格式化字符串。例如,LEFT 函数将返回字符串左侧特定数量的字符。在以下示例中,查询将返回以字母 A 开头的所有州:
LEFT(STATE_NAME,1) = 'A'
有关支持的函数列表,请参阅 DBMS 文档。
数字
无论您的区域设置如何,小数点 (.) 将始终用作小数分隔符。在表达式中不能使用逗号作为小数分隔符或千位分隔符。
可以使用等于 (=)、不等于 (<>)、大于 (>)、小于 (<)、大于等于 (>=) 和小于等于 (<=) 和 BETWEEN 运算符查询数值。例如:
POPULATION >= 5000
数值函数可用来格式化数值。例如,ROUND 函数可将文件地理数据库中的数值四舍五入到指定的小数位数:
ROUND(SQKM,0) = 500
有关支持的数值函数列表,请参阅 DBMS 文档。
日期和时间
基本规则
地理数据库数据源将日期保存在日期时间字段中。但是,ArcInfo coverage 和 shapefile 不是这样。
因此,下面所列的大部分查询语法都包含对时间的引用。在某些情况下,当已知字段只包含日期时,查询中的时间部分可以安全地省略掉;而在其他情况下则需要声明,否则查询将返回语法错误。
ArcMap 日期格式的主要目的是存储日期,不是时间。当基础数据库实际上使用日期时间字段时,可以在此字段中只存储时间,但最好不要这样做。查询时间会比较麻烦;例如,12:30:05 p.m. 会被存储为 '1899-12-30 12:30:05'。
本部分内容的目的只是帮助您查询日期值,而非时间值。当存储了包含非空时间的日期(例如 1999 年 1 月 12 日 04:00:00)后,只查询该日期将不会返回这条记录,因为当向一个日期时间字段只传递日期时,系统会自动用零填充时间,所以将只检索该日期下时间为 12:00:00 a.m 的记录。
属性表内会以用户友好的格式来显示日期和时间(取决于用户的区域设置)而不是采用基础数据库的格式。这在大多数情况下都很适用,但也有一些缺点:
- 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. 或其他等效的值(取决于您的区域设置)。
ArcSDE 地理数据库的日期时间语法
Informix
Datefield = 'yyyy-mm-dd hh:mm:ss'
查询的 hh:mm:ss 部分不能省略,即使等于 00:00:00 也是如此。
Oracle
Datefield = date 'yyyy-mm-dd'
请切记,这将不会返回时间不为空的记录。
在 Oracle 中查询日期的替代格式如下:
Datefield = TO_DATE('yyyy-mm-dd hh:mm:ss','YYYY-MM-DD HH24:MI:SS')
第二个参数 'YYYY-MM-DD HH24:MI:SS' 用于描述查询要用的格式。实际的查询可能类似于:
Datefield = TO_DATE('2003-01-08 14:35:00','YYYY-MM-DD HH24:MI:SS')
您可以使用精简形式:
TO_DATE('2003-11-18','YYYY-MM-DD')
同样,这将不会返回时间不为空的记录。
SQL Server
Datefield = 'yyyy-mm-dd hh:mm:ss'
当记录中未设置时间时,查询的 hh:mm:ss 部分可以省略。
替代格式如下:
Datefield = 'mm/dd/yyyy'
IBM DB2
Datefield = TO_DATE('yyyy-mm-dd hh:mm:ss','YYYY-MM-DD HH24:MI:SS')
查询的 hh:mm:ss 部分不能省略,即使时间等于 00:00:00 也是如此。
PostgreSQL
Datefield = TIMESTAMP 'YYYY-MM-DD HH24:MI:SS' Datefield = TIMESTAMP 'YYYY-MM-DD'
使用“等于”查询时必须指定完整的时间戳,否则将不会返回任何记录。如果查询的表中包含这些确切的时间戳(2007-05-29 00:00:00 或 2007-05-29 12:14:25)时,您可以用下列语句成功进行查询:
select * from table where date = '2007-05-29 00:00:00';
或者
select * from table where date = '2007-05-29 12:14:25';
如果使用其他运算符(如大于、小于、大于等于或小于等于),您不必指定时间,不过如果您希望更精确些也可以指定。以下两个语句都可以使用:
select * from table where date < '2007-05-29';
select * from table where date < '2007-05-29 12:14:25';
文件地理数据库、shapefile、coverage 和其他基于文件的数据源
文件地理数据库、shapefile 和 coverage 中的日期前面要加上 date。
"Datefield" = date 'yyyy-mm-dd'
文件地理数据库支持在日期字段中使用时间,因此可将此加入到表达式中:
"Datefield" = date 'yyyy-mm-dd hh:mm:ss'
Shapefile 和 coverage 不支持在日期字段中使用时间。
个人地理数据库
个人地理数据库中的日期使用井号 (#) 来分隔。
例如:
[Datefield] = #mm-dd-yyyy hh:mm:ss#
可以将其精简为 [Datefield] = #mm-dd-yyyy#。
替代格式
[Datefield] = #yyyy/mm/dd#
已知局限性
对连接的左侧部分(第一张表)的日期查询只适用于基于文件的数据源,如文件地理数据库、shapefile 和 DBF 表。不过,对于非基于文件的数据,如个人地理数据库数据和 ArcSDE 数据也有解决方法,如下文所述。
当使用为基于文件的数据源所开发的受限的 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' 的所有记录,而无论每条记录是否是连接匹配项。
子查询
子查询是指嵌套在另一个查询中的查询。子查询可用于应用谓词或聚合函数,或将数据与存储在另一张表中的值进行比较。可使用 IN 或 ANY 关键字来完成。例如,以下查询只会选择未列在表 indep_countries 中的国家:
"COUNTRY_NAME" NOT IN (SELECT "COUNTRY_NAME" FROM indep_countries)
此查询将返回国家中 GDP2006 大于 GDP2005 的所有要素:
"GDP2006" > (SELECT MAX("GDP2005") FROM countries)
对于表中的每条记录,子查询可能需要在其目标表中分析所有数据。在大型数据集上执行时可能极其缓慢。
文件地理数据库仅提供对以下子查询的支持:
- IN 谓词。例如:
"COUNTRY_NAME" NOT IN (SELECT "COUNTRY_NAME" FROM indep_countries)
- 包含比较运算符的标量子查询。标量子查询返回单个值。例如:
"GDP2006" > (SELECT MAX("GDP2005") FROM countries)
对于文件地理数据库,集合函数 AVG、COUNT、MIN、MAX 和 SUM 只能用在标量子查询内。 - EXISTS 谓词。例如:
EXISTS (SELECT * FROM indep_countries WHERE "COUNTRY_NAME" = 'Mexico')
运算符
以下是文件地理数据库、shapefile、coverage 和其他基于文件的数据源所支持的查询运算符的完整列表。个人地理数据库和 ArcSDE 地理数据库也支持这些运算符,但这些数据源可能使用不同的语法。除了以下这些运算符外,个人地理数据库和 ArcSDE 地理数据库还支持一些其他功能。有关详细信息,请参阅 DBMS 文档。
算术运算符
算术运算符用于对数值进行加、减、乘、除的运算。
运算符 | 描述 |
---|---|
* | 乘法算术运算符 |
/ | 除法算术运算符 |
+ | 加法算术运算符 |
- | 减法算术运算符 |
比较运算符
使用比较运算符可以将两个表达式进行比较。
运算符 | 描述 |
---|---|
< | 小于。适用于字符串(基于字母顺序进行比较)、数值和日期。 |
<= | 小于或等于。适用于字符串(基于字母顺序进行比较)、数值和日期。 |
<> | 不等于。适用于字符串(基于字母顺序进行比较)、数值和日期。 |
> | 大于。适用于字符串(基于字母顺序进行比较)、数值和日期。 |
>= | 大于或等于。适用于字符串(基于字母顺序进行比较)、数值和日期。例如,以下查询将选择名称的开头字母是 M 到 Z 的所有城市: "CITY_NAME" >= 'M' |
[NOT] BETWEEN x AND y | 选择值大于等于 x 且小于等于 y 的记录。如果前面有 NOT,则将选择值在指定范围之外的记录。例如,以下表达式将选择值大于等于 1 且小于等于 10 的所有记录: "OBJECTID" BETWEEN 1 AND 10这与以下表达式等效: "OBJECTID" >= 1 AND OBJECTID <= 10但是,在查询具有索引的字段时使用包含 BETWEEN 的表达式效率会更高。 |
[NOT] EXISTS | 如果子查询返回至少一条记录则返回 TRUE;否则返回 FALSE。例如,如果 OBJECTID 字段包含一个值 50,则以下查询将返回 TRUE: EXISTS (SELECT * FROM parcels WHERE "OBJECTID" = 50)只有文件地理数据库、个人地理数据库和 ArcSDE 地理数据库支持 EXISTS。 |
[NOT] IN | 如果记录的某个字段包含多个字符串或值的其中一个,那么选择这条记录。当表达式前面包含 NOT 时,如果记录的某个字段不包含多个字符串或值的任何一个,那么将选择这条记录。例如,以下表达式将搜索四个不同的州名称: "STATE_NAME" IN ('Alabama', 'Alaska', 'California', 'Florida')对于文件地理数据库、个人地理数据库和 ArcSDE 地理数据库,此运算符还可用于子查询: "STATE_NAME" IN (SELECT "STATE_NAME" FROM states WHERE "POP" > 5000000) |
IS [NOT] NULL | 选择指定字段为空值的记录。如果 NULL 前面有 NOT,则将选择指定字段中包含任意值的记录。例如,以下表达式将选择 POPULATION 中包含空值的所有记录: "POPULATION" IS NULL |
x [NOT] LIKE y [ESCAPE '转义字符'] | 将 LIKE 运算符(不是 = 运算符)与通配符结合使用可以构建对部分字符串的搜索。例如,以下表达式将从美国州名中选择 Mississippi 和 Missouri: "STATE_NAME" LIKE 'Miss%'百分号 (%) 表示这个位置可以是任意字符,即 1 个字符、100 个字符或者无字符均可。此外,如果您希望在查询时通配符仅代表一个字符,可使用下划线 (_)。例如,以下表达式将找到 Catherine Smith 和 Katherine Smith: "OWNER_NAME" LIKE '_atherine Smith'百分号和下划线通配符适用于任何基于文件的数据或多用户地理数据库数据。LIKE 表达式的两侧都要有字符数据。如果需要访问非字符数据,请使用 CAST 函数。例如,以下查询将返回整数字段 SCORE_INT 中以 8 开头的数值: CAST ("SCORE_INT" AS VARCHAR) LIKE '8%'要在搜索字符串中包含百分号或下划线,请使用 ESCAPE 关键字来将另一种字符指定为转义字符,该字符表示紧接其后的是真正的百分号或下划线。例如,以下表达式将返回任何包含 10% 的任何字符串,例如 10% DISCOUNT 或 A10%: "AMOUNT" LIKE '%10$%%' ESCAPE '$'查询个人地理数据库时,使用通配符星号 (*) 代表任意数量的字符,而使用问号 (?) 代表 一个字符。还可以使用井号 (#) 通配符来表示匹配单个数字(数值型值)。例如,以下查询将从个人地理数据库返回宗地编号 A1、A2 等等: [PARCEL_NUMBER] LIKE 'A#' |
逻辑运算符
运算符 | 描述 |
---|---|
AND | 结合两个条件,如果两个条件都为 true 则选择该记录。例如,以下表达式将选择面积大于 1,500 平方英尺且有一个能容纳 2 台以上汽车的车库的所有房屋: "AREA" > 1500 AND "GARAGE" > 2 |
OR | 结合两个条件,如果两个条件中至少有一个为 true 则选择该记录。例如,以下表达式将选择面积大于 1,500 平方英尺或有一个能容纳 2 台以上汽车的车库的所有房屋: "AREA" > 1500 OR "GARAGE" > 2 |
NOT | 选择与表达式不匹配的记录。例如,以下表达式将选择除 California 之外的所有州: NOT "STATE_NAME" = 'California' |
字符串运算符
运算符 | 描述 |
---|---|
|| | 同时返回连接两个或多个字符串表达式后得到的字符串。 FIRST_NAME || MIDDLE_NAME || LAST_NAME |
函数
以下是文件地理数据库、shapefile、coverage 和其他基于文件的数据源所支持的函数的完整列表。个人地理数据库和 ArcSDE 地理数据库也支持这些函数,但这些数据源可能使用不同的语法或函数名。除了以下这些函数外,个人地理数据库和 ArcSDE 地理数据库还支持一些其他功能。有关详细信息,请参阅 DBMS 文档。
日期函数
函数 | 说明 |
---|---|
CURRENT_DATE | 返回当前日期。 |
EXTRACT(extract_field FROM extract_source) | 返回 extract_source. 的 extract_field 部分。extract_source 参数是一个日期时间表达式。extract_field 参数可以是下列任一关键字:年、月、日、小时、分钟或秒。 |
CURRENT TIME | 返回当前时间。 |
字符串函数
以 string_exp 表示的参数可以是列名、字符串文本或者另一个标量函数的结果,其基础数据类型可表示为字符型。
以 character_exp 表示的参数是长度可变的字符型字符串。
以 start 或 length 表示的参数可以是数值文本或者另一个标量函数的结果,其基础数据类型可表示为数值型。
这些字符串函数以 1 为基础;即字符串的第一个字符为字符 1。
函数 | 说明 |
---|---|
CHAR_LENGTH(string_exp) | 返回字符串表达式的字符长度。 |
LOWER(string_exp) | 返回一个与 string_exp 相等的字符串,其中所有大写字符均会转换为小写字符。 |
POSITION(character_exp IN character_exp) | 返回第一个字符表达式在第二个字符表达式中的位置。结果是一个确切的数值,采用预先定义的精度且小数位数为零。 |
SUBSTRING(string_exp FROM start FOR length) | 返回一个从 string_exp 衍生而来的字符串,其起始字符位置由 start 指定,字符数由 length 指定。 |
TRIM(BOTH | LEADING | TRAILING trim_character FROM string_exp) | 返回字符串的开头、末尾或两端移除 trim_character 后所得的 string_exp。 |
UPPER(string_exp) | 返回一个与 string_exp 相等的字符串,其中所有小写字符均会转换为大写字符。 |
数值函数
所有数值函数均返回数值型值。
以 numeric_exp、float_exp 或 integer_exp 表示的参数可以是列名、另一个标量函数的结果或数值文本,其基础数据类型可表示为数值型。
函数 | 说明 |
---|---|
ABS(numeric_exp) | 返回 numeric_exp 的绝对值。 |
ACOS(float_exp) | 返回作为角度的 float_exp 的反余弦值,用弧度表示。 |
ASIN(float_exp) | 返回作为角度的 float_exp 的反正弦值,用弧度表示。 |
ATAN(float_exp) | 返回作为角度的 float_exp 的反正切值,用弧度表示。 |
CEILING(numeric_exp) | 返回大于或等于 numeric_exp 的最小整数。 |
COS(float_exp) | 返回 float_exp 的余弦值,其中 float_exp 是以弧度表示的角度。 |
FLOOR(numeric_exp) | 返回小于或等于 numeric_exp 的最大整数。 |
LOG(float_exp) | 返回 float_exp 的自然对数。 |
LOG10(float_exp) | 返回 float_exp 的以 10 为底的对数。 |
MOD(integer_exp1, integer_exp2) | 返回 integer_exp1 除以 integer_exp2 所得的余数。 |
POWER(numeric_exp, integer_exp) | 返回 numeric_exp 的 integer_exp 次幂的值。 |
ROUND(numeric_exp, integer_exp) | 返回四舍五入至小数点右侧第 integer_exp 位的 numeric_exp。如果 integer_exp 为负数,则 numeric_exp 将被四舍五入至小数点左侧第 |integer_exp| 位。 |
SIGN(numeric_exp) | 返回 numeric_exp 正负号的标志。如果 numeric_exp 小于零,则返回 -1。如果 numeric_exp 等于零,则返回 0。如果 numeric_exp 大于零,则返回 1。 |
SIN(float_exp) | 返回 float_exp 的正弦值,其中 float_exp 是以弧度表示的角度。 |
TAN(float_exp) | 返回 float_exp 的正切值,其中 float_exp 是以弧度表示的角度。 |
TRUNCATE(numeric_exp, integer_exp) | 返回截断至小数点右侧第 integer_exp 位的 numeric_exp。如果 integer_exp 为负数,则 numeric_exp 将被截断至小数点左侧第 |integer_exp| 位。 |
CAST 函数
CAST 函数可将值转换为指定的数据类型。语法如下:
CAST(exp AS data_type)
exp 参数可以是列名、另一个标量函数的结果或是一个文本。Data_type 可以是下列任意关键字,可以用大写或小写形式指定:CHAR、VARCHAR、INTEGER、SMALLINT、REAL、DOUBLE、DATE、TIME、DATETIME、NUMERIC 或 DECIMAL。
有关 CAST 函数的详细信息,请参阅 CAST 和 CONVERT。