ANSI 兼容性
在 Spark SQL 中,有两个选项可以与 SQL 标准兼容:spark.sql.ansi.enabled
和 spark.sql.storeAssignmentPolicy
(有关详细信息,请参见下表)。
当 spark.sql.ansi.enabled
设置为 true
时,Spark SQL 使用 ANSI 兼容的方言,而不是 Hive 兼容的方言。例如,如果 SQL 运算符/函数的输入无效,Spark 将在运行时抛出异常,而不是返回空结果。一些 ANSI 方言功能可能不是直接来自 ANSI SQL 标准,但它们的行为与 ANSI SQL 的风格一致。
此外,Spark SQL 具有一个独立的选项来控制在表中插入行时的隐式转换行为。转换行为在标准中定义为存储分配规则。
当 spark.sql.storeAssignmentPolicy
设置为 ANSI
时,Spark SQL 符合 ANSI 存储分配规则。这是一个单独的配置,因为它的默认值为 ANSI
,而配置 spark.sql.ansi.enabled
默认情况下是禁用的。
属性名称 | 默认值 | 含义 | 自版本 |
---|---|---|---|
spark.sql.ansi.enabled |
false | 当为 true 时,Spark 尝试符合 ANSI SQL 规范 1. Spark SQL 将在无效操作上抛出运行时异常,包括整数溢出错误、字符串解析错误等。 2. Spark 将使用不同的类型强制转换规则来解决数据类型之间的冲突。这些规则始终基于数据类型优先级。 |
3.0.0 |
spark.sql.storeAssignmentPolicy |
ANSI | 在将值插入与不同数据类型匹配的列时,Spark 将执行类型转换。目前,我们支持 3 种类型强制转换规则策略:ANSI、legacy 和 strict。 1. 使用 ANSI 策略,Spark 按照 ANSI SQL 执行类型强制转换。在实践中,行为与 PostgreSQL 大致相同。它不允许某些不合理的类型转换,例如将字符串转换为整数或将双精度转换为布尔值。在插入数值类型列时,如果值超出目标数据类型的范围,将抛出溢出错误。 2. 使用 legacy 策略,Spark 允许类型强制转换,只要它是有效的 Cast,这非常宽松。例如,允许将字符串转换为整数或将双精度转换为布尔值。这也是 Spark 2.x 中唯一的行为,并且与 Hive 兼容。 3. 使用 strict 策略,Spark 不允许类型强制转换中出现任何可能的精度损失或数据截断,例如,不允许将双精度转换为整数或将十进制转换为双精度。 |
3.0.0 |
以下小节介绍了在启用 ANSI 模式时算术运算、类型转换和 SQL 解析中的行为变化。对于 Spark SQL 中的类型转换,有三种类型,本文将逐一介绍:cast、存储分配和类型强制转换。
算术运算
在 Spark SQL 中,默认情况下不会检查对数值类型(十进制除外)执行的算术运算是否溢出。这意味着如果操作导致溢出,结果与 Java/Scala 程序中的相应操作相同(例如,如果 2 个整数的总和大于可表示的最大值,则结果为负数)。另一方面,Spark SQL 对十进制溢出返回 null。当 spark.sql.ansi.enabled
设置为 true
并且在数值和间隔算术运算中发生溢出时,它将在运行时抛出算术异常。
-- `spark.sql.ansi.enabled=true`
SELECT 2147483647 + 1;
org.apache.spark.SparkArithmeticException: [ARITHMETIC_OVERFLOW] integer overflow. Use 'try_add' to tolerate overflow and return NULL instead. If necessary set spark.sql.ansi.enabled to "false" to bypass this error.
== SQL(line 1, position 8) ==
SELECT 2147483647 + 1
^^^^^^^^^^^^^^
SELECT abs(-2147483648);
org.apache.spark.SparkArithmeticException: [ARITHMETIC_OVERFLOW] integer overflow. If necessary set spark.sql.ansi.enabled to "false" to bypass this error.
-- `spark.sql.ansi.enabled=false`
SELECT 2147483647 + 1;
+----------------+
|(2147483647 + 1)|
+----------------+
| -2147483648|
+----------------+
SELECT abs(-2147483648);
+----------------+
|abs(-2147483648)|
+----------------+
| -2147483648|
+----------------+
Cast
当 spark.sql.ansi.enabled
设置为 true
时,通过 CAST
语法进行的显式转换对于标准中定义的非法转换模式(例如,从字符串到整数的转换)会抛出运行时异常。
此外,ANSI SQL 模式不允许以下类型转换,这些转换在 ANSI 模式关闭时是允许的
- 数值 <=> 二进制
- 日期 <=> 布尔值
- 时间戳 <=> 布尔值
- 日期 => 数值
下表给出了 CAST
表达式中源数据类型和目标数据类型的有效组合。“Y” 表示组合在语法上是有效的,没有限制,“N” 表示组合无效。
源\目标 | 数值 | 字符串 | 日期 | 时间戳 | 时间戳_NTZ | 间隔 | 布尔值 | 二进制 | 数组 | 映射 | 结构 |
---|---|---|---|---|---|---|---|---|---|---|---|
数值 | Y | Y | N | Y | N | Y | Y | N | N | N | N |
字符串 | Y | Y | Y | Y | Y | Y | Y | Y | N | N | N |
日期 | N | Y | Y | Y | Y | N | N | N | N | N | N |
时间戳 | Y | Y | Y | Y | Y | N | N | N | N | N | N |
时间戳_NTZ | N | Y | Y | Y | Y | N | N | N | N | N | N |
间隔 | Y | Y | N | N | N | Y | N | N | N | N | N |
布尔值 | Y | Y | N | N | N | N | Y | N | N | N | N |
二进制 | N | Y | N | N | N | N | N | Y | N | N | N |
数组 | N | Y | N | N | N | N | N | N | Y | N | N |
映射 | N | Y | N | N | N | N | N | N | N | Y | N |
结构 | N | Y | N | N | N | N | N | N | N | N | Y |
在上表中,所有使用新语法的 CAST
都标记为红色 Y
- CAST(数值 AS 数值):如果值超出目标数据类型的范围,则引发溢出异常。
- CAST(字符串 AS (数值/日期/时间戳/时间戳_NTZ/间隔/布尔值)):如果值无法解析为目标数据类型,则引发运行时异常。
- CAST(时间戳 AS 数值):如果自纪元以来的秒数超出目标数据类型的范围,则引发溢出异常。
- CAST(数值 AS 时间戳):如果数值乘以 1000000(每秒微秒)超出 Long 类型的范围,则引发溢出异常。
- CAST(数组 AS 数组):如果元素的转换有任何问题,则引发异常。
- CAST(映射 AS 映射):如果键和值的转换有任何问题,则引发异常。
- CAST(结构 AS 结构):如果结构字段的转换有任何问题,则引发异常。
- CAST(数值 AS 字符串):在将十进制值转换为字符串时,始终使用纯字符串表示,而不是在需要指数时使用科学记数法
- CAST(间隔 AS 数值):如果日时间隔的微秒数或年月时间隔的月数超出目标数据类型的范围,则引发溢出异常。
- CAST(数值 AS 间隔):如果数值乘以目标间隔的结束单位超出 Int 类型的范围(对于年月时间隔)或 Long 类型的范围(对于日时间隔),则引发溢出异常。
-- Examples of explicit casting
-- `spark.sql.ansi.enabled=true`
SELECT CAST('a' AS INT);
org.apache.spark.SparkNumberFormatException: [CAST_INVALID_INPUT] The value 'a' of the type "STRING" cannot be cast to "INT" because it is malformed. Correct the value as per the syntax, or change its target type. Use `try_cast` to tolerate malformed input and return NULL instead. If necessary set "spark.sql.ansi.enabled" to "false" to bypass this error.
== SQL(line 1, position 8) ==
SELECT CAST('a' AS INT)
^^^^^^^^^^^^^^^^
SELECT CAST(2147483648L AS INT);
org.apache.spark.SparkArithmeticException: [CAST_OVERFLOW] The value 2147483648L of the type "BIGINT" cannot be cast to "INT" due to an overflow. Use `try_cast` to tolerate overflow and return NULL instead. If necessary set "spark.sql.ansi.enabled" to "false" to bypass this error.
SELECT CAST(DATE'2020-01-01' AS INT);
org.apache.spark.sql.AnalysisException: cannot resolve 'CAST(DATE '2020-01-01' AS INT)' due to data type mismatch: cannot cast date to int.
To convert values from date to int, you can use function UNIX_DATE instead.
-- `spark.sql.ansi.enabled=false` (This is a default behaviour)
SELECT CAST('a' AS INT);
+--------------+
|CAST(a AS INT)|
+--------------+
| null|
+--------------+
SELECT CAST(2147483648L AS INT);
+-----------------------+
|CAST(2147483648 AS INT)|
+-----------------------+
| -2147483648|
+-----------------------+
SELECT CAST(DATE'2020-01-01' AS INT)
+------------------------------+
|CAST(DATE '2020-01-01' AS INT)|
+------------------------------+
| null|
+------------------------------+
-- Examples of store assignment rules
CREATE TABLE t (v INT);
-- `spark.sql.storeAssignmentPolicy=ANSI`
INSERT INTO t VALUES ('1');
org.apache.spark.sql.AnalysisException: [INCOMPATIBLE_DATA_FOR_TABLE.CANNOT_SAFELY_CAST] Cannot write incompatible data for table `spark_catalog`.`default`.`t`: Cannot safely cast `v`: "STRING" to "INT".
-- `spark.sql.storeAssignmentPolicy=LEGACY` (This is a legacy behaviour until Spark 2.x)
INSERT INTO t VALUES ('1');
SELECT * FROM t;
+---+
| v|
+---+
| 1|
+---+
转换中的舍入
将带有小数部分的十进制数转换为以 SECOND 为结束单位的间隔类型(如 INTERVAL HOUR TO SECOND)时,Spark 会将小数部分舍入到“最近的邻居”,除非两个邻居的距离相等,在这种情况下,将向上舍入。
存储分配
如开头所述,当 spark.sql.storeAssignmentPolicy
设置为 ANSI
(这是默认值)时,Spark SQL 在表插入时符合 ANSI 存储分配规则。下表给出了表插入中源数据类型和目标数据类型的有效组合。
源\目标 | 数值 | 字符串 | 日期 | 时间戳 | 时间戳_NTZ | 间隔 | 布尔值 | 二进制 | 数组 | 映射 | 结构 |
---|---|---|---|---|---|---|---|---|---|---|---|
数值 | Y | Y | N | N | N | N | N | N | N | N | N |
字符串 | N | Y | N | N | N | N | N | N | N | N | N |
日期 | N | Y | Y | Y | Y | N | N | N | N | N | N |
时间戳 | N | Y | Y | Y | Y | N | N | N | N | N | N |
时间戳_NTZ | N | Y | Y | Y | Y | N | N | N | N | N | N |
间隔 | N | Y | N | N | N | N* | N | N | N | N | N |
布尔值 | N | Y | N | N | N | N | Y | N | N | N | N |
二进制 | N | Y | N | N | N | N | N | Y | N | N | N |
数组 | N | N | N | N | N | N | N | N | Y** | N | N |
映射 | N | N | N | N | N | N | N | N | N | Y** | N |
结构 | N | N | N | N | N | N | N | N | N | N | Y** |
* Spark 不支持间隔类型表列。
** 对于数组/映射/结构类型,数据类型检查规则递归地应用于其组件元素。
在表插入期间,Spark 将在数值溢出时抛出异常。
CREATE TABLE test(i INT);
INSERT INTO test VALUES (2147483648L);
org.apache.spark.SparkArithmeticException: [CAST_OVERFLOW_IN_TABLE_INSERT] Fail to insert a value of "BIGINT" type into the "INT" type column `i` due to an overflow. Use `try_cast` on the input value to tolerate overflow and return NULL instead.
类型强制转换
类型提升和优先级
当 spark.sql.ansi.enabled
设置为 true
时,Spark SQL 使用几个规则来控制如何解决数据类型之间的冲突。这些冲突解决的核心是类型优先级列表,它定义了给定数据类型的值是否可以隐式提升为另一种数据类型。
数据类型 | 优先级列表(从最窄到最宽) |
---|---|
字节 | 字节 -> 短整型 -> 整型 -> 长整型 -> 十进制 -> 浮点型* -> 双精度 |
短整型 | 短整型 -> 整型 -> 长整型 -> 十进制 -> 浮点型* -> 双精度 |
整型 | 整型 -> 长整型 -> 十进制 -> 浮点型* -> 双精度 |
长整型 | 长整型 -> 十进制 -> 浮点型* -> 双精度 |
十进制 | 十进制 -> 浮点型* -> 双精度 |
浮点型 | 浮点型 -> 双精度 |
双精度 | 双精度 |
日期 | 日期 -> 时间戳_NTZ -> 时间戳 |
时间戳 | 时间戳 |
字符串 | 字符串、长整型 -> 双精度、日期 -> 时间戳_NTZ -> 时间戳、布尔值、二进制** |
二进制 | 二进制 |
布尔值 | 布尔值 |
间隔 | 间隔 |
映射 | 映射*** |
数组 | 数组*** |
结构 | 结构*** |
* 为了最小公倍数解析,跳过浮点型以避免精度损失。
** 字符串可以提升为多种数据类型。请注意,字节/短整型/整型/十进制/浮点型不在此优先级列表中。字节/短整型/整型和字符串之间的最小公倍数是长整型,而十进制/浮点型之间的最小公倍数是双精度。
*** 对于复杂类型,优先级规则递归地应用于其组件元素。
特殊规则适用于无类型的 NULL。NULL 可以提升为任何其他类型。
这是优先级列表的图形表示,作为一棵有向树:
最小公倍数解析
一组类型中的最小公倍数是从优先级列表中所有类型集元素都可达到的最窄类型。
最小公倍数解析用于
- 为期望多个参数共享参数类型的函数推导出参数类型,例如 coalesce、least 或 greatest。
- 为运算符推导出操作数类型,例如算术运算或比较。
- 为表达式推导出结果类型,例如 case 表达式。
- 为数组和映射构造函数推导出元素、键或值类型。如果最小公倍数解析为 FLOAT,则会应用特殊规则。对于浮点型值,如果任何类型是 INT、BIGINT 或 DECIMAL,则最小公倍数将推送到 DOUBLE 以避免潜在的数字丢失。
-- The coalesce function accepts any set of argument types as long as they share a least common type.
-- The result type is the least common type of the arguments.
> SET spark.sql.ansi.enabled=true;
> SELECT typeof(coalesce(1Y, 1L, NULL));
BIGINT
> SELECT typeof(coalesce(1, DATE'2020-01-01'));
Error: Incompatible types [INT, DATE]
> SELECT typeof(coalesce(ARRAY(1Y), ARRAY(1L)));
ARRAY<BIGINT>
> SELECT typeof(coalesce(1, 1F));
DOUBLE
> SELECT typeof(coalesce(1L, 1F));
DOUBLE
> SELECT (typeof(coalesce(1BD, 1F)));
DOUBLE
> SELECT typeof(coalesce(1, '2147483648'))
BIGINT
> SELECT typeof(coalesce(1.0, '2147483648'))
DOUBLE
> SELECT typeof(coalesce(DATE'2021-01-01', '2022-01-01'))
DATE
SQL 函数
函数调用
在 ANSI 模式下(spark.sql.ansi.enabled=true),Spark SQL 的函数调用
- 一般来说,它遵循
存储分配
规则,将输入值存储为 SQL 函数的声明参数类型 - 特殊规则适用于无类型的 NULL。NULL 可以提升为任何其他类型。
> SET spark.sql.ansi.enabled=true;
-- implicitly cast Int to String type
> SELECT concat('total number: ', 1);
total number: 1
-- implicitly cast Timestamp to Date type
> select datediff(now(), current_date);
0
-- implicitly cast String to Double type
> SELECT ceil('0.1');
1
-- special rule: implicitly cast NULL to Date type
> SELECT year(null);
NULL
> CREATE TABLE t(s string);
-- Can't store String column as Numeric types.
> SELECT ceil(s) from t;
Error in query: cannot resolve 'CEIL(spark_catalog.default.t.s)' due to data type mismatch
-- Can't store String column as Date type.
> select year(s) from t;
Error in query: cannot resolve 'year(spark_catalog.default.t.s)' due to data type mismatch
具有不同行为的函数
在 ANSI 模式下 (spark.sql.ansi.enabled=true
),某些 SQL 函数的行为可能会有所不同。
size
: 此函数对空输入返回 null。element_at
:- 如果使用无效索引,此函数将抛出
ArrayIndexOutOfBoundsException
。
- 如果使用无效索引,此函数将抛出
elt
: 如果使用无效索引,此函数将抛出ArrayIndexOutOfBoundsException
。parse_url
: 如果输入字符串不是有效的 URL,此函数将抛出IllegalArgumentException
。to_date
: 如果输入字符串无法解析或模式字符串无效,此函数应抛出异常。to_timestamp
: 如果输入字符串无法解析或模式字符串无效,此函数应抛出异常。unix_timestamp
: 如果输入字符串无法解析或模式字符串无效,此函数应抛出异常。to_unix_timestamp
: 如果输入字符串无法解析或模式字符串无效,此函数应抛出异常。make_date
: 如果结果日期无效,此函数应抛出异常。make_timestamp
: 如果结果时间戳无效,此函数应抛出异常。make_interval
: 如果结果间隔无效,此函数应抛出异常。next_day
: 如果输入不是有效的星期几,此函数将抛出IllegalArgumentException
。
SQL 运算符
在 ANSI 模式下 (spark.sql.ansi.enabled=true
),某些 SQL 运算符的行为可能会有所不同。
array_col[index]
: 如果使用无效索引,此运算符将抛出ArrayIndexOutOfBoundsException
。
ANSI 模式下的有用函数
在 ANSI 模式开启时,它会对无效操作抛出异常。可以使用以下 SQL 函数来抑制此类异常。
try_cast
: 与CAST
相同,只是它在运行时错误时返回NULL
结果,而不是抛出异常。try_add
: 与加法运算符+
相同,只是它在整数溢出时返回NULL
结果,而不是抛出异常。try_subtract
: 与减法运算符-
相同,只是它在整数溢出时返回NULL
结果,而不是抛出异常。try_multiply
: 与乘法运算符*
相同,只是它在整数溢出时返回NULL
结果,而不是抛出异常。try_divide
: 与除法运算符/
相同,只是它在除以 0 时返回NULL
结果,而不是抛出异常。try_sum
: 与函数sum
相同,只是它在整数/十进制/间隔值溢出时返回NULL
结果,而不是抛出异常。try_avg
: 与函数avg
相同,只是它在十进制/间隔值溢出时返回NULL
结果,而不是抛出异常。try_element_at
: 与函数element_at
相同,只是它在数组索引越界时返回NULL
结果,而不是抛出异常。try_to_timestamp
: 与函数to_timestamp
相同,只是它在字符串解析错误时返回NULL
结果,而不是抛出异常。
SQL 关键字(可选,默认情况下禁用)
当 spark.sql.ansi.enabled
和 spark.sql.ansi.enforceReservedKeywords
都为 true 时,Spark SQL 将使用 ANSI 模式解析器。
使用 ANSI 模式解析器,Spark SQL 有两种类型的关键字
- 非保留关键字:仅在特定上下文中具有特殊含义的关键字,可以在其他上下文中用作标识符。例如,
EXPLAIN SELECT ...
是一个命令,但 EXPLAIN 可以用作其他地方的标识符。 - 保留关键字:保留的关键字,不能用作表、视图、列、函数、别名等的标识符。
使用默认解析器,Spark SQL 有两种类型的关键字
- 非保留关键字:与 ANSI 模式启用时相同定义。
- 严格非保留关键字:非保留关键字的严格版本,不能用作表别名。
默认情况下,spark.sql.ansi.enabled
和 spark.sql.ansi.enforceReservedKeywords
都为 false。
以下是 Spark SQL 中所有关键字的列表。
关键字 | Spark SQL ANSI 模式 |
Spark SQL 默认模式 |
SQL-2016 |
---|---|---|---|
ADD | 非保留 | 非保留 | 非保留 |
AFTER | 非保留 | 非保留 | 非保留 |
ALL | 保留 | 非保留 | 保留 |
ALTER | 非保留 | 非保留 | 保留 |
ALWAYS | 非保留 | 非保留 | 非保留 |
ANALYZE | 非保留 | 非保留 | 非保留 |
AND | 保留 | 非保留 | 保留 |
ANTI | 非保留 | 严格非保留 | 非保留 |
ANY | 保留 | 非保留 | 保留 |
ANY_VALUE | 非保留 | 非保留 | 非保留 |
ARCHIVE | 非保留 | 非保留 | 非保留 |
ARRAY | 非保留 | 非保留 | 保留 |
AS | 保留 | 非保留 | 保留 |
ASC | 非保留 | 非保留 | 非保留 |
AT | 非保留 | 非保留 | 保留 |
AUTHORIZATION | 保留 | 非保留 | 保留 |
BETWEEN | 非保留 | 非保留 | 保留 |
BIGINT | 非保留 | 非保留 | 保留 |
BINARY | 非保留 | 非保留 | 保留 |
BOOLEAN | 非保留 | 非保留 | 保留 |
BOTH | 保留 | 非保留 | 保留 |
BUCKET | 非保留 | 非保留 | 非保留 |
BUCKETS | 非保留 | 非保留 | 非保留 |
BY | 非保留 | 非保留 | 保留 |
BYTE | 非保留 | 非保留 | 非保留 |
CACHE | 非保留 | 非保留 | 非保留 |
CASCADE | 非保留 | 非保留 | 非保留 |
CASE | 保留 | 非保留 | 保留 |
CAST | 保留 | 非保留 | 保留 |
CATALOG | 非保留 | 非保留 | 非保留 |
CATALOGS | 非保留 | 非保留 | 非保留 |
CHANGE | 非保留 | 非保留 | 非保留 |
CHAR | 非保留 | 非保留 | 保留 |
CHARACTER | 非保留 | 非保留 | 保留 |
CHECK | 保留 | 非保留 | 保留 |
CLEAR | 非保留 | 非保留 | 非保留 |
CLUSTER | 非保留 | 非保留 | 非保留 |
CLUSTERED | 非保留 | 非保留 | 非保留 |
CODEGEN | 非保留 | 非保留 | 非保留 |
COLLATE | 保留 | 非保留 | 保留 |
COLLECTION | 非保留 | 非保留 | 非保留 |
COLUMN | 保留 | 非保留 | 保留 |
COLUMNS | 非保留 | 非保留 | 非保留 |
COMMENT | 非保留 | 非保留 | 非保留 |
COMMIT | 非保留 | 非保留 | 保留 |
COMPACT | 非保留 | 非保留 | 非保留 |
COMPACTIONS | 非保留 | 非保留 | 非保留 |
COMPUTE | 非保留 | 非保留 | 非保留 |
CONCATENATE | 非保留 | 非保留 | 非保留 |
CONSTRAINT | 保留 | 非保留 | 保留 |
COST | 非保留 | 非保留 | 非保留 |
CREATE | 保留 | 非保留 | 保留 |
CROSS | 保留 | 严格非保留 | 保留 |
CUBE | 非保留 | 非保留 | 保留 |
CURRENT | 非保留 | 非保留 | 保留 |
CURRENT_DATE | 保留 | 非保留 | 保留 |
CURRENT_TIME | 保留 | 非保留 | 保留 |
CURRENT_TIMESTAMP | 保留 | 非保留 | 保留 |
CURRENT_USER | 保留 | 非保留 | 保留 |
DATA | 非保留 | 非保留 | 非保留 |
DATE | 非保留 | 非保留 | 保留 |
DATABASE | 非保留 | 非保留 | 非保留 |
DATABASES | 非保留 | 非保留 | 非保留 |
DATEADD | 非保留 | 非保留 | 非保留 |
DATE_ADD | 非保留 | 非保留 | 非保留 |
DATEDIFF | 非保留 | 非保留 | 非保留 |
DATE_DIFF | 非保留 | 非保留 | 非保留 |
DAY | 非保留 | 非保留 | 非保留 |
DAYS | 非保留 | 非保留 | 非保留 |
DAYOFYEAR | 非保留 | 非保留 | 非保留 |
DBPROPERTIES | 非保留 | 非保留 | 非保留 |
DEC | 非保留 | 非保留 | 保留 |
DECIMAL | 非保留 | 非保留 | 保留 |
DEFAULT | 非保留 | 非保留 | 非保留 |
DEFINED | 非保留 | 非保留 | 非保留 |
DELETE | 非保留 | 非保留 | 保留 |
DELIMITED | 非保留 | 非保留 | 非保留 |
DESC | 非保留 | 非保留 | 非保留 |
DESCRIBE | 非保留 | 非保留 | 保留 |
DFS | 非保留 | 非保留 | 非保留 |
DIRECTORIES | 非保留 | 非保留 | 非保留 |
DIRECTORY | 非保留 | 非保留 | 非保留 |
DISTINCT | 保留 | 非保留 | 保留 |
DISTRIBUTE | 非保留 | 非保留 | 非保留 |
DIV | 非保留 | 非保留 | 不是关键字 |
DOUBLE | 非保留 | 非保留 | 保留 |
DROP | 非保留 | 非保留 | 保留 |
ELSE | 保留 | 非保留 | 保留 |
END | 保留 | 非保留 | 保留 |
ESCAPE | 保留 | 非保留 | 保留 |
ESCAPED | 非保留 | 非保留 | 非保留 |
EXCEPT | 保留 | 严格非保留 | 保留 |
EXCHANGE | 非保留 | 非保留 | 非保留 |
EXCLUDE | 非保留 | 非保留 | 非保留 |
EXISTS | 非保留 | 非保留 | 保留 |
EXPLAIN | 非保留 | 非保留 | 非保留 |
EXPORT | 非保留 | 非保留 | 非保留 |
EXTENDED | 非保留 | 非保留 | 非保留 |
EXTERNAL | 非保留 | 非保留 | 保留 |
EXTRACT | 非保留 | 非保留 | 保留 |
FALSE | 保留 | 非保留 | 保留 |
FETCH | 保留 | 非保留 | 保留 |
FIELDS | 非保留 | 非保留 | 非保留 |
FILTER | 保留 | 非保留 | 保留 |
FILEFORMAT | 非保留 | 非保留 | 非保留 |
FIRST | 非保留 | 非保留 | 非保留 |
FLOAT | 非保留 | 非保留 | 保留 |
FOLLOWING | 非保留 | 非保留 | 非保留 |
FOR | 保留 | 非保留 | 保留 |
FOREIGN | 保留 | 非保留 | 保留 |
FORMAT | 非保留 | 非保留 | 非保留 |
FORMATTED | 非保留 | 非保留 | 非保留 |
FROM | 保留 | 非保留 | 保留 |
FULL | 保留 | 严格非保留 | 保留 |
FUNCTION | 非保留 | 非保留 | 保留 |
FUNCTIONS | 非保留 | 非保留 | 非保留 |
GENERATED | 非保留 | 非保留 | 非保留 |
GLOBAL | 非保留 | 非保留 | 保留 |
GRANT | 保留 | 非保留 | 保留 |
GROUP | 保留 | 非保留 | 保留 |
GROUPING | 非保留 | 非保留 | 保留 |
HAVING | 保留 | 非保留 | 保留 |
HOUR | 非保留 | 非保留 | 非保留 |
HOURS | 非保留 | 非保留 | 非保留 |
IDENTIFIER | 非保留 | 非保留 | 非保留 |
IF | 非保留 | 非保留 | 不是关键字 |
IGNORE | 非保留 | 非保留 | 非保留 |
IMPORT | 非保留 | 非保留 | 非保留 |
IN | 保留 | 非保留 | 保留 |
INCLUDE | 非保留 | 非保留 | 非保留 |
INDEX | 非保留 | 非保留 | 非保留 |
INDEXES | 非保留 | 非保留 | 非保留 |
INNER | 保留 | 严格非保留 | 保留 |
INPATH | 非保留 | 非保留 | 非保留 |
INPUTFORMAT | 非保留 | 非保留 | 非保留 |
INSERT | 非保留 | 非保留 | 保留 |
INT | 非保留 | 非保留 | 保留 |
INTEGER | 非保留 | 非保留 | 保留 |
INTERSECT | 保留 | 严格非保留 | 保留 |
INTERVAL | 非保留 | 非保留 | 保留 |
INTO | 保留 | 非保留 | 保留 |
IS | 保留 | 非保留 | 保留 |
ITEMS | 非保留 | 非保留 | 非保留 |
JOIN | 保留 | 严格非保留 | 保留 |
KEYS | 非保留 | 非保留 | 非保留 |
LAST | 非保留 | 非保留 | 非保留 |
LATERAL | 保留 | 严格非保留 | 保留 |
LAZY | 非保留 | 非保留 | 非保留 |
LEADING | 保留 | 非保留 | 保留 |
LEFT | 保留 | 严格非保留 | 保留 |
LIKE | 非保留 | 非保留 | 保留 |
ILIKE | 非保留 | 非保留 | 非保留 |
LIMIT | 非保留 | 非保留 | 非保留 |
LINES | 非保留 | 非保留 | 非保留 |
LIST | 非保留 | 非保留 | 非保留 |
LOAD | 非保留 | 非保留 | 非保留 |
LOCAL | 非保留 | 非保留 | 保留 |
LOCATION | 非保留 | 非保留 | 非保留 |
LOCK | 非保留 | 非保留 | 非保留 |
LOCKS | 非保留 | 非保留 | 非保留 |
LOGICAL | 非保留 | 非保留 | 非保留 |
LONG | 非保留 | 非保留 | 非保留 |
MACRO | 非保留 | 非保留 | 非保留 |
MAP | 非保留 | 非保留 | 非保留 |
MATCHED | 非保留 | 非保留 | 非保留 |
MERGE | 非保留 | 非保留 | 非保留 |
MICROSECOND | 非保留 | 非保留 | 非保留 |
MICROSECONDS | 非保留 | 非保留 | 非保留 |
MILLISECOND | 非保留 | 非保留 | 非保留 |
MILLISECONDS | 非保留 | 非保留 | 非保留 |
MINUTE | 非保留 | 非保留 | 非保留 |
MINUTES | 非保留 | 非保留 | 非保留 |
MINUS | 非保留 | 严格非保留 | 非保留 |
MONTH | 非保留 | 非保留 | 非保留 |
MONTHS | 非保留 | 非保留 | 非保留 |
MSCK | 非保留 | 非保留 | 非保留 |
NAME | 非保留 | 非保留 | 非保留 |
NAMESPACE | 非保留 | 非保留 | 非保留 |
NAMESPACES | 非保留 | 非保留 | 非保留 |
NANOSECOND | 非保留 | 非保留 | 非保留 |
NANOSECONDS | 非保留 | 非保留 | 非保留 |
NATURAL | 保留 | 严格非保留 | 保留 |
NO | 非保留 | 非保留 | 保留 |
NOT | 保留 | 非保留 | 保留 |
NULL | 保留 | 非保留 | 保留 |
NULLS | 非保留 | 非保留 | 非保留 |
NUMERIC | 非保留 | 非保留 | 非保留 |
OF | 非保留 | 非保留 | 保留 |
OFFSET | 保留 | 非保留 | 保留 |
ON | 保留 | 严格非保留 | 保留 |
ONLY | 保留 | 非保留 | 保留 |
OPTION | 非保留 | 非保留 | 非保留 |
OPTIONS | 非保留 | 非保留 | 非保留 |
OR | 保留 | 非保留 | 保留 |
ORDER | 保留 | 非保留 | 保留 |
OUT | 非保留 | 非保留 | 保留 |
OUTER | 保留 | 非保留 | 保留 |
OUTPUTFORMAT | 非保留 | 非保留 | 非保留 |
OVER | 非保留 | 非保留 | 非保留 |
OVERLAPS | 保留 | 非保留 | 保留 |
OVERLAY | 非保留 | 非保留 | 非保留 |
OVERWRITE | 非保留 | 非保留 | 非保留 |
PARTITION | 非保留 | 非保留 | 保留 |
PARTITIONED | 非保留 | 非保留 | 非保留 |
PARTITIONS | 非保留 | 非保留 | 非保留 |
PERCENT | 非保留 | 非保留 | 非保留 |
PERCENTILE_CONT | 保留 | 非保留 | 非保留 |
PERCENTILE_DISC | 保留 | 非保留 | 非保留 |
PIVOT | 非保留 | 非保留 | 非保留 |
PLACING | 非保留 | 非保留 | 非保留 |
POSITION | 非保留 | 非保留 | 保留 |
PRECEDING | 非保留 | 非保留 | 非保留 |
PRIMARY | 保留 | 非保留 | 保留 |
PRINCIPALS | 非保留 | 非保留 | 非保留 |
PROPERTIES | 非保留 | 非保留 | 非保留 |
PURGE | 非保留 | 非保留 | 非保留 |
QUARTER | 非保留 | 非保留 | 非保留 |
QUERY | 非保留 | 非保留 | 非保留 |
RANGE | 非保留 | 非保留 | 保留 |
REAL | 非保留 | 非保留 | 保留 |
RECORDREADER | 非保留 | 非保留 | 非保留 |
RECORDWRITER | 非保留 | 非保留 | 非保留 |
RECOVER | 非保留 | 非保留 | 非保留 |
REDUCE | 非保留 | 非保留 | 非保留 |
REFERENCES | 保留 | 非保留 | 保留 |
REFRESH | 非保留 | 非保留 | 非保留 |
REGEXP | 非保留 | 非保留 | 不是关键字 |
RENAME | 非保留 | 非保留 | 非保留 |
REPAIR | 非保留 | 非保留 | 非保留 |
REPEATABLE | 非保留 | 非保留 | 非保留 |
REPLACE | 非保留 | 非保留 | 非保留 |
RESET | 非保留 | 非保留 | 非保留 |
RESPECT | 非保留 | 非保留 | 非保留 |
RESTRICT | 非保留 | 非保留 | 非保留 |
REVOKE | 非保留 | 非保留 | 保留 |
RIGHT | 保留 | 严格非保留 | 保留 |
RLIKE | 非保留 | 非保留 | 非保留 |
ROLE | 非保留 | 非保留 | 非保留 |
ROLES | 非保留 | 非保留 | 非保留 |
ROLLBACK | 非保留 | 非保留 | 保留 |
ROLLUP | 非保留 | 非保留 | 保留 |
ROW | 非保留 | 非保留 | 保留 |
ROWS | 非保留 | 非保留 | 保留 |
SCHEMA | 非保留 | 非保留 | 非保留 |
SCHEMAS | 非保留 | 非保留 | 非保留 |
SECOND | 非保留 | 非保留 | 非保留 |
SECONDS | 非保留 | 非保留 | 非保留 |
SELECT | 保留 | 非保留 | 保留 |
SEMI | 非保留 | 严格非保留 | 非保留 |
SEPARATED | 非保留 | 非保留 | 非保留 |
SERDE | 非保留 | 非保留 | 非保留 |
SERDEPROPERTIES | 非保留 | 非保留 | 非保留 |
SESSION_USER | 保留 | 非保留 | 保留 |
SET | 非保留 | 非保留 | 保留 |
SETS | 非保留 | 非保留 | 非保留 |
SHORT | 非保留 | 非保留 | 非保留 |
SHOW | 非保留 | 非保留 | 非保留 |
SKEWED | 非保留 | 非保留 | 非保留 |
SMALLINT | 非保留 | 非保留 | 保留 |
SOME | 保留 | 非保留 | 保留 |
SORT | 非保留 | 非保留 | 非保留 |
SORTED | 非保留 | 非保留 | 非保留 |
SOURCE | 非保留 | 非保留 | 非保留 |
START | 非保留 | 非保留 | 保留 |
STATISTICS | 非保留 | 非保留 | 非保留 |
STORED | 非保留 | 非保留 | 非保留 |
STRATIFY | 非保留 | 非保留 | 非保留 |
STRING | 非保留 | 非保留 | 非保留 |
STRUCT | 非保留 | 非保留 | 非保留 |
SUBSTR | 非保留 | 非保留 | 非保留 |
SUBSTRING | 非保留 | 非保留 | 非保留 |
SYNC | 非保留 | 非保留 | 非保留 |
SYSTEM_TIME | 非保留 | 非保留 | 非保留 |
SYSTEM_VERSION | 非保留 | 非保留 | 非保留 |
TABLE | 保留 | 非保留 | 保留 |
TABLES | 非保留 | 非保留 | 非保留 |
TABLESAMPLE | 非保留 | 非保留 | 保留 |
TARGET | 非保留 | 非保留 | 非保留 |
TBLPROPERTIES | 非保留 | 非保留 | 非保留 |
TEMP | 非保留 | 非保留 | 不是关键字 |
TEMPORARY | 非保留 | 非保留 | 非保留 |
TERMINATED | 非保留 | 非保留 | 非保留 |
THEN | 保留 | 非保留 | 保留 |
TIME | 保留 | 非保留 | 保留 |
TIMESTAMP | 非保留 | 非保留 | 非保留 |
TIMESTAMP_LTZ | 非保留 | 非保留 | 非保留 |
TIMESTAMP_NTZ | 非保留 | 非保留 | 非保留 |
TIMESTAMPADD | 非保留 | 非保留 | 非保留 |
TIMESTAMPDIFF | 非保留 | 非保留 | 非保留 |
TINYINT | 非保留 | 非保留 | 非保留 |
TO | 保留 | 非保留 | 保留 |
TOUCH | 非保留 | 非保留 | 非保留 |
TRAILING | 保留 | 非保留 | 保留 |
TRANSACTION | 非保留 | 非保留 | 非保留 |
TRANSACTIONS | 非保留 | 非保留 | 非保留 |
TRANSFORM | 非保留 | 非保留 | 非保留 |
TRIM | 非保留 | 非保留 | 非保留 |
TRUE | 非保留 | 非保留 | 保留 |
TRUNCATE | 非保留 | 非保留 | 保留 |
TRY_CAST | 非保留 | 非保留 | 非保留 |
TYPE | 非保留 | 非保留 | 非保留 |
UNARCHIVE | 非保留 | 非保留 | 非保留 |
UNBOUNDED | 非保留 | 非保留 | 非保留 |
UNCACHE | 非保留 | 非保留 | 非保留 |
UNION | 保留 | 严格非保留 | 保留 |
UNIQUE | 保留 | 非保留 | 保留 |
UNKNOWN | 保留 | 非保留 | 保留 |
UNLOCK | 非保留 | 非保留 | 非保留 |
UNPIVOT | 非保留 | 非保留 | 非保留 |
UNSET | 非保留 | 非保留 | 非保留 |
UPDATE | 非保留 | 非保留 | 保留 |
USE | 非保留 | 非保留 | 非保留 |
USER | 保留 | 非保留 | 保留 |
USING | 保留 | 严格非保留 | 保留 |
VALUES | 非保留 | 非保留 | 保留 |
VARCHAR | 非保留 | 非保留 | 保留 |
VERSION | 非保留 | 非保留 | 非保留 |
VIEW | 非保留 | 非保留 | 非保留 |
VIEWS | 非保留 | 非保留 | 非保留 |
VOID | 非保留 | 非保留 | 非保留 |
WEEK | 非保留 | 非保留 | 非保留 |
WEEKS | 非保留 | 非保留 | 非保留 |
WHEN | 保留 | 非保留 | 保留 |
WHERE | 保留 | 非保留 | 保留 |
WINDOW | 非保留 | 非保留 | 保留 |
WITH | 保留 | 非保留 | 保留 |
WITHIN | 保留 | 非保留 | 保留 |
X | 非保留 | 非保留 | 非保留 |
YEAR | 非保留 | 非保留 | 非保留 |
YEARS | 非保留 | 非保留 | 非保留 |
ZONE | 非保留 | 非保留 | 非保留 |