ArcGIS Server 包含一个安全选项,可强制开发人员在通过 REST 或 SOAP 使用地图、要素、图像和 WFS 服务时使用标准化 SQL 查询。 此选项使开发人员和应用程序查询 ArcGIS Server 服务更为简便,并有助于防止 SQL 注入攻击。 默认情况下强制使用标准化查询,但是服务器管理员可以禁用标准化查询。
标准化查询
启用标准化查询后,ArcGIS Server 将检查标准语法,并且不支持数据库特定的函数和语法。 如果您是一名应用程序开发人员,并且正在使用数据库特定函数和语法,则必须更新应用程序代码中的 where 子句以使用 ArcGIS 所支持的常规 SQL 语法。 或者,可以禁止 ArcGIS Server 检查标准化查询。
标准化查询限制
标准化查询会应用于整个 ArcGIS Server 站点;不会只对某些服务启用而对其他服务禁用标准化查询。
不同工作空间之间的连接不支持标准化查询。 此外,通过 OLE DB 连接文件访问的数据库表不受支持。 如果服务数据包含这些源,则必须使用替代方法来引用数据。
不支持子查询作为 where 子句,如 POP_2010 = (SELECT min(POP_2010)) FROM counties。
编写标准化查询
本主题末尾的表格介绍了 ArcGIS Server 所支持的 SQL 函数。 此表格能够帮助您了解哪些 SQL 函数可用于生成标准化查询,这些标准化查询可用于应用程序中的地图、要素、影像以及 WFS 服务。
确定 ArcGIS Server 是否正在使用标准化查询
如上所述,标准化查询为默认启用并应用于 ArcGIS Server 站点中的所有地图、要素、影像以及 WFS 服务。 但是,服务器管理员可通过登录到 ArcGIS Server Administrator Directory 并浏览至系统 > 属性 > 更新,来验证正在使用的标准化查询。 如果系统属性对话框未显示系统属性或显示 {"standardizedQueries": "true"},则标准化查询处于开启状态。
除此之外,管理员、应用程序开发人员和客户可通过使用 ArcGIS Server Services Directory 访问服务并查看使用标准化查询属性,来验证是否正在使用标准化查询。 对于地图、要素和 WFS 服务,可通过访问服务中的特定图层或表来查看此属性,例如 https://gisserver.domain.com:6443/arcgis/rest/services/folder/service/service type/0。 对于影像服务,可在服务端点找到此属性,例如 https://gisserver.domain.com:6443/arcgis/rest/services/folder/service/ImageServer。
有关如何访问 Administrator Directory 的说明或了解如何禁用标准化查询的信息,请参阅该主题的下一部分。
禁用标准化查询
如果需要在应用程序中使用数据库特定的 where 子句语句,则可以通过访问 ArcGIS Server Administrator Directory 禁用标准化查询。 要执行此操作,请遵循以下说明。
警告:
禁用此安全选项,您的站点更易受到 SQL 注入攻击。
注:
ArcGIS Enterprise 中的托管要素服务不支持禁用标准化查询。
- 打开 Administrator Directory,然后以具有管理权限的用户身份登录到站点。
Administrator Directory 通常位于 https://gisserver.domain.com:6443/arcgis/admin。
- 单击系统 > 属性 > 更新。
- 在操作 - 更新 页面,在系统属性对话框中输入以下字符串:
{"standardizedQueries": "false"} - 单击更新。
- 重新启动 ArcGIS Server。
您的站点现已配置为允许用户使用非标准化查询向地图、要素、图像和 WFS 服务发送请求。 要重新启用标准化查询,请重复执行以上说明并将 standardizedQueries 属性设置为 true。
ArcGIS Server 中支持的 SQL 函数
下表显示了 ArcGIS Server 支持的 SQL 函数以及每个 SQL 函数的语法。 在您的应用程序中使用下列函数和语法时,ArcGIS Server 会对其进行转换,使其符合服务使用的数据库规范。
这些函数适用于 ArcGIS Server web 服务,而不适用于托管 web 图层。
| 函数类型 | 函数 | 描述 | 示例 |
|---|---|---|---|
日期 | CURRENT_DATE | 返回会话时区的当前日期。 注:托管会话时区始终为 UTC。 | Datefield < CURRENT_DATE |
CURRENT_TIME | 返回会话时区的当前时间。 注:托管会话时区始终为 UTC。 | Timestampfield < CURRENT_TIME | |
CURRENT_TIMESTAMP | 返回当前本地时间。 注:托管会话时区始终为 UTC。 | Timestampfield < CURRENT_TIMESTAMP | |
EXTRACT(extract_field FROM extract_source) | 返回 extract_source 的 extract_field 部分。 extract_field 参数可以是下列任一关键字:年、月、日、小时、分钟或秒。 | 搜索十一月的所有行: EXTRACT(MONTH FROM Datefield) = 11 | |
数学分析 | ABS(numeric_exp) | 返回指定的数值表达式的绝对(正)值。 | ABS(-99)=90 |
ACOS(numeric_exp) | 以角度形式返回 numeric_exp 的反余弦值,用弧度表示。 | ||
ASIN(numeric_exp) | 以角度形式返回 numeric_exp 的反正弦值,用弧度表示。 | ||
ATAN(numeric_exp) | 以角度形式返回 numeric_exp 的反正切值,用弧度表示。 | ||
CEILING(numeric_exp) | 返回大于或等于指定的数值表达式的最小整数。 | 查找 numeric_exp 的上限整数等于所需值的所有行: CEILING(ratings)=90 | |
COS(numeric_exp) | 以角度形式返回 numeric_exp 的余弦值,用弧度表示。 | ||
COSH(numeric_exp) | 以角度形式返回 numeric_exp 的双曲余弦值,用弧度表示。 | ||
FLOOR(numeric_exp) | 返回小于或等于指定的数值表达式的最大整数。 | 查找 numeric_exp 的下限整数等于所需值的所有行: FLOOR(ratings)=75 | |
LOG(float_exp) | 返回指定的浮点表达式的自然对数。 | ||
LOG10(float_exp) | 返回指定的浮点表达式的以 10 为底的对数。 | ||
MOD(integer_exp1, integer_exp2) | 返回 integer_exp1 除以 integer_exp2 所得的余数。 | 查找 integer_exp1 为偶数的所有行: MOD(userid,2)=0 | |
POWER(numeric_exp, integer_exp) | 返回指定幂值的指定表达式的值。 | POWER(Numericfield, 2) = 16 | |
ROUND(numeric_exp, integer_exp) | 返回数值,四舍五入到指定长度或指定精度。 | ||
SIGN(numeric_exp) | 返回 numeric_exp 的数学符号的指示符。 示例:数值为零时返回 0,为正数时返回 1,为负数时返回 -1。 | 搜索 numeric_exp 为负数的所有行: SIGN(elevation)=-1 | |
SIN(numeric_exp) | 以角度形式返回 numeric_exp 的正弦值,用弧度表示。 | ||
SINH(numeric_exp) | 以角度形式返回 numeric_exp 的双曲正弦值,用弧度表示。 | ||
TAN(numeric_exp) | 以角度形式返回 numeric_exp 的正切值,用弧度表示。 | ||
TANH(numeric_exp) | 以角度形式返回 numeric_exp 的双曲正切值,用弧度表示。 | ||
TRUNCATE(numeric_exp, integer_exp) | 返回截断至小数点右侧第 integer_exp 位的 numeric_exp,但不对该值进行四舍五入。 | TRUNCATE(0.5463111445,3)=0.546 | |
聚合 | AVG(numeric_exp, integer_exp) | 返回 numeric_exp 中值的计算平均值。 | outStatistics=[{"statisticType": "avg","onStatisticField": "pop1997","outStatisticFieldName": "avg_pop1997"}] |
COUNT(string_exp OR ASTERISK) | 返回具有 string_exp 的行数。 | outStatistics=[{"statisticType": "count","onStatisticField": "p_females","outStatisticFieldName": "count_p_females"}] | |
MAX(numeric_exp) MAX(string_exp) MAX(datetime_exp) | 返回 numeric_exp、string_exp 或 datetime_exp 中的最大值。 | 查找所有 numeric_exp 行中的最大值: outStatistics=[{"statisticType": "max","onStatisticField": "p_males","outStatisticFieldName": "max_p_males"}] | |
MIN(numeric_exp) MIN(numeric_exp) MIN(numeric_exp) | 返回 numeric_exp、string_exp 或 datetime_exp 中的最小值。 | 查找所有 numeric_exp 行中的最小值: outStatistics=[{"statisticType": "min","onStatisticField": "pop1990","outStatisticFieldName": "min_pop1990"}] | |
STDDEV(numeric_exp) | 返回 numeric_exp 中值的标准差。 | 查找所有 numeric_exp 行中的标准差值: outStatistics=[{"statisticType": "stddev","onStatisticField": "eval_score","outStatisticFieldName": "stddev_eval_score"}] | |
SUM(numeric_exp) | 返回 numeric_exp 中的值的总和。 | 查找所有 numeric_exp 行中的值的总和: outStatistics=[{"statisticType": "sum","onStatisticField": "p_females","outStatisticFieldName": "sum_p_females"}] | |
VAR(numeric_exp) | 返回 numeric_exp 中的值的方差。 | 查找所有 numeric_exp 行中的方差值: outStatistics=[{"statisticType": "var","onStatisticField": "pop1980","outStatisticFieldName": "var_pop1980"}] | |
字符串 | CHAR_LENGTH(string_exp) | 返回输入字符串的字符长度。 | 搜索 string_exp 长度大于 10 的所有行: CHAR_LENGTH(string_exp) > 10 |
CONCAT(string_exp1, string_exp2) | 返回连接两个或多个字符串值后得到的字符串。 | 输出包含连接字符的 string_exp1 和 string_exp2 的连接版本: OutFields=CONCAT(id,CONCAT(I-,name)) | |
LOWER(string_exp) | 返回一个与 string_exp 相等的字符串,其中所有大写字符均会转换为小写字符。 默认区域设置为数据库的区域设置。 | 搜索值为所需字符串的所有行,不考虑大小写: LOWER(string_field) = "lowered_string" | |
POSITION(cahracter_exp1 IN character_exp2) | 返回 character_exp1 在 character_exp2 中首次出现位置的整数值。 | 搜索第一个字符为“I”的所有行: POSITION('I' IN state_name) = 1 | |
SUBSTRING(string_exp FROM start FOR length) SUBSTRING(string_exp, integer_exp_start, integer_exp_length) | 返回一个从 string_exp 衍生而来的字符串,其起始字符位置由 start 指定,字符数由 length 指定。 | 搜索 Stringfield 中值的前两个字符为 Ch 的所有行: SUBSTRING(Stringfield FROM 1 FOR 2)='Ch' | |
TRIM(BOTH|LEADING|TRAILING trim_character FROM string_exp) | 返回字符串的开头、末尾或两端移除 trim_character 后所得的 string_exp。 | 输出不含不需要的前缀和后缀的 string_field: OutFields=TRIM(BOTH '__' FROM string_exp) | |
UPPER(string_exp) | 返回一个与 string_exp 相等的字符串,其中所有小写字符均会转换为大写字符。 默认区域设置为数据库的区域设置。 | UPPER(name) = "TEXAS" | |
其他 | CAST(expression AS target_data_type) | 返回转换为 target_data_type 的表达式。 | 搜索转换为指定数据类型的表达式等于所需值的所有行: CAST(parcel_id AS INT)=38456 |
COALESCE(expression1,expression2,...) | 返回表达式列表中的第一个非空值。 | 搜索第一个非空值为指定值的所有行: COALESCE(preferred_name, nickname, first_name) = 'MyName' | |
CURRENT_USER | 返回当前登录用户。 注:不会返回当前数据库用户。 | 搜索当前登录用户为唯一工作人员的所有行。 workerfield=CURRENT_USER搜索当前登录用户列为工作人员的所有行,不考虑是否存在其他工作人员。 position(CURRENT_USER in workerfield) > 0 | |
NULLIF(expression1,expression2) | 比较两个表达式。 如果相等,则返回 NULL。 如果不相等,则返回 expression1。 | 输出 expression1 和 expression2 之间的 NULLIF 比较结果: outFields=NULLIF(units_sold, unit_sell_goal) |