ANSI 合规性

在 Spark SQL 中,有两种选项可用于遵守 SQL 标准:spark.sql.ansi.enabledspark.sql.storeAssignmentPolicy(详见下表)。

默认情况下,spark.sql.ansi.enabledtrue,Spark SQL 使用符合 ANSI 标准的方言,而不是 Hive 方言。例如,如果 SQL 运算符/函数的输入无效,Spark 将在运行时抛出异常而不是返回 null 结果。一些 ANSI 方言特性可能不是直接来自 ANSI SQL 标准,但其行为与 ANSI SQL 的风格保持一致。

此外,Spark SQL 还有一个独立的选项来控制在向表中插入行时的隐式类型转换行为。这些类型转换行为在标准中被定义为存储赋值规则。

默认情况下,spark.sql.storeAssignmentPolicyANSI,Spark SQL 遵守 ANSI 存储赋值规则。

属性名称默认值含义起始版本
spark.sql.ansi.enabled true 当为 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 基本相同。它禁止某些不合理的类型转换,例如将字符串转换为 int 或将 double 转换为 boolean。在插入数值类型列时,如果值超出目标数据类型的范围,将抛出溢出错误。
2. 使用 legacy 策略,只要是有效的 Cast,Spark 就允许类型强制转换,这非常宽松。例如,允许将字符串转换为 int 或将 double 转换为 boolean。这也是 Spark 2.x 中唯一的行为,并且与 Hive 兼容。
3. 使用 strict 策略,Spark 不允许类型强制转换中出现任何可能的精度损失或数据截断,例如,不允许将 double 转换为 int 或将 decimal 转换为 double。
3.0.0

以下小节将介绍启用 ANSI 模式时算术运算、类型转换和 SQL 解析中的行为变化。对于 Spark SQL 中的类型转换,有三种类型,本文将逐一介绍:cast、存储赋值和类型强制转换。

算术运算

在 Spark SQL 中,默认情况下,Spark 会在运行时对间隔类型和数值类型溢出抛出算术异常。如果 spark.sql.ansi.enabledfalse,则十进制类型将生成 null 值,其他数值类型的行为与 Java/Scala 程序中相应的操作相同(例如,如果两个整数的和高于可表示的最大值,结果将是负数),这是 Spark 3 或更早版本的行为。

-- `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”表示该组合无效。

源\目标 数值 字符串 日期 时间戳 Timestamp_NTZ 间隔 布尔 二进制 数组 Map Struct
数值 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
Timestamp_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
Map N Y N N N N N N N Y N
Struct N Y N N N N N N N N Y

在上表中,所有使用新语法的 CAST 都标记为红色 Y

-- Examples of explicit casting

-- `spark.sql.ansi.enabled=true` (This is a default behaviour)
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.
== 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.

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`
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|
+---+

Cast 中的舍入

在将带小数部分的 decimal 类型转换为以 SECOND 为结束单位的间隔类型(例如 INTERVAL HOUR TO SECOND)时,Spark 会将小数部分四舍五入到“最近的邻居”,除非两个邻居等距,此时向上舍入。

存储赋值

如开头所述,当 spark.sql.storeAssignmentPolicy 设置为 ANSI(默认值)时,Spark SQL 在表插入时遵循 ANSI 存储赋值规则。下表给出了表插入中源数据类型和目标数据类型的有效组合。

源\目标 数值 字符串 日期 时间戳 Timestamp_NTZ 间隔 布尔 二进制 数组 Map Struct
数值 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
Timestamp_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
Map N N N N N N N N N Y** N
Struct N N N N N N N N N N Y**

* Spark 不支持间隔类型表列。

** 对于 Array/Map/Struct 类型,数据类型检查规则递归地应用于其组成元素。

在表插入期间,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 使用一些规则来管理数据类型冲突的解决方式。这种冲突解决的核心是类型优先级列表,它定义了给定数据类型的值是否可以隐式提升为另一种数据类型。

数据类型 优先级列表(从最窄到最宽)
Byte Byte -> Short -> Int -> Long -> Decimal -> Float* -> Double
Short Short -> Int -> Long -> Decimal-> Float* -> Double
Int Int -> Long -> Decimal -> Float* -> Double
Long Long -> Decimal -> Float* -> Double
Decimal Decimal -> Float* -> Double
Float Float -> Double
Double Double
日期 Date -> Timestamp_NTZ -> Timestamp
时间戳 时间戳
字符串 String, Long -> Double, Date -> Timestamp_NTZ -> Timestamp , Boolean, Binary **
二进制 二进制
布尔 布尔
间隔 间隔
Map Map***
数组 Array***
Struct Struct***

* 为了最小公共类型解析,跳过 float 以避免精度损失。

** String 可以提升为多种数据类型。请注意,Byte/Short/Int/Decimal/Float 不在此优先级列表中。Byte/Short/Int 和 String 之间的最小公共类型是 Long,而 Decimal/Float 之间的最小公共类型是 Double。

*** 对于复杂类型,优先级规则递归地应用于其组成元素。

特殊规则适用于无类型 NULL。NULL 可以提升为任何其他类型。

这是优先级列表的图形表示,为一个有向树:类型优先级列表

最小公共类型解析

一组类型中的最小公共类型是从优先级列表中可由该组所有元素达到的最窄类型。

最小公共类型解析用于

Decimal 类型在这里稍微复杂一些,因为它不是一个简单类型,而是有参数:精度 (precision) 和 小数位数 (scale)。一个 decimal(precision, scale) 表示该值在整数部分最多可以有 precision - scale 位数字,在小数部分可以有 scale 位数字。Decimal 类型之间的最小公共类型应该在整数部分和小数部分都有足够的位数来表示所有值。更精确地说,decimal(p1, s1)decimal(p2, s2) 之间的最小公共类型的小数位数为 max(s1, s2),精度为 max(s1, s2) + max(p1 - s1, p2 - s2)。然而,Spark 中的 decimal 类型最大精度为 38。如果最终的 decimal 类型需要更高的精度,我们必须进行截断。由于整数部分的数字更重要,Spark 会首先截断小数部分的数字。例如,decimal(48, 20) 将被截断为 decimal(38, 10)

请注意,算术运算有特殊的规则来计算十进制输入的最小公共类型

操作 结果精度 结果小数位数
e1 + e2 max(s1, s2) + max(p1 - s1, p2 - s2) + 1 max(s1, s2)
e1 - e2 max(s1, s2) + max(p1 - s1, p2 - s2) + 1 max(s1, s2)
e1 * e2 p1 + p2 + 1 s1 + s2
e1 / e2 p1 - s1 + s2 + max(6, s1 + p2 + 1) max(6, s1 + p2 + 1)
e1 % e2 min(p1 - s1, p2 - s2) + max(s1, s2) max(s1, s2)

算术运算的截断规则也不同:它们在小数部分至少保留 6 位数字,这意味着我们只能将 scale 减少到 6。在这种情况下可能会发生溢出。

-- 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 的函数调用

> 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 函数的行为可能不同。

SQL 运算符

在 ANSI 模式下(spark.sql.ansi.enabled=true),一些 SQL 运算符的行为可能不同。

ANSI 模式的有用函数

当 ANSI 模式开启时,它会为无效操作抛出异常。您可以使用以下 SQL 函数来抑制此类异常。

SQL 关键字(可选,默认禁用)

spark.sql.ansi.enabledspark.sql.ansi.enforceReservedKeywords 都为 true 时,Spark SQL 将使用 ANSI 模式解析器。

使用 ANSI 模式解析器,Spark SQL 有两种关键字

使用默认解析器,Spark SQL 有两种关键字

默认情况下,spark.sql.ansi.enforceReservedKeywords 为 false。

以下是 Spark SQL 中所有关键字的列表。

关键字 Spark SQL
ANSI 模式
Spark SQL
非 ANSI 模式
SQL-2016
ADD 非保留 非保留 非保留
AFTER 非保留 非保留 非保留
AGGREGATE 非保留 非保留 非保留
ALL 保留 非保留 保留
ALTER 非保留 非保留 保留
ALWAYS 非保留 非保留 非保留
ANALYZE 非保留 非保留 非保留
AND 保留 非保留 保留
ANTI 非保留 严格非保留 非保留
ANY 保留 非保留 保留
ANY_VALUE 非保留 非保留 非保留
ARCHIVE 非保留 非保留 非保留
ARRAY 非保留 非保留 保留
AS 保留 非保留 保留
ASC 非保留 非保留 非保留
AT 非保留 非保留 保留
ATOMIC 非保留 非保留 非保留
AUTHORIZATION 保留 非保留 保留
BEGIN 非保留 非保留 非保留
BETWEEN 非保留 非保留 保留
BIGINT 非保留 非保留 保留
BINARY 非保留 非保留 保留
BINDING 非保留 非保留 非保留
BOOLEAN 非保留 非保留 保留
BOTH 保留 非保留 保留
BUCKET 非保留 非保留 非保留
BUCKETS 非保留 非保留 非保留
BY 非保留 非保留 保留
BYTE 非保留 非保留 非保留
CACHE 非保留 非保留 非保留
CALL 保留 非保留 保留
CALLED 非保留 非保留 非保留
CASCADE 非保留 非保留 非保留
CASE 保留 非保留 保留
CAST 保留 非保留 保留
CATALOG 非保留 非保留 非保留
CATALOGS 非保留 非保留 非保留
CHANGE 非保留 非保留 非保留
CHAR 非保留 非保留 保留
CHARACTER 非保留 非保留 保留
CHECK 保留 非保留 保留
CLEAR 非保留 非保留 非保留
CLUSTER 非保留 非保留 非保留
CLUSTERED 非保留 非保留 非保留
CODEGEN 非保留 非保留 非保留
COLLATE 保留 非保留 保留
COLLATION 保留 非保留 保留
COLLECTION 非保留 非保留 非保留
COLUMN 保留 非保留 保留
COLUMNS 非保留 非保留 非保留
COMMENT 非保留 非保留 非保留
COMMIT 非保留 非保留 保留
COMPACT 非保留 非保留 非保留
COMPACTIONS 非保留 非保留 非保留
COMPENSATION 非保留 非保留 非保留
COMPUTE 非保留 非保留 非保留
CONCATENATE 非保留 非保留 非保留
CONDITION 非保留 非保留 非保留
CONSTRAINT 保留 非保留 保留
CONTAINS 非保留 非保留 非保留
CONTINUE 非保留 非保留 非保留
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 非保留 非保留 保留
DECLARE 非保留 非保留 非保留
DEFAULT 非保留 非保留 非保留
DEFINED 非保留 非保留 非保留
DEFINER 非保留 非保留 非保留
DELETE 非保留 非保留 保留
DELIMITED 非保留 非保留 非保留
DESC 非保留 非保留 非保留
DESCRIBE 非保留 非保留 保留
DETERMINISTIC 非保留 非保留 保留
DFS 非保留 非保留 非保留
DIRECTORIES 非保留 非保留 非保留
DIRECTORY 非保留 非保留 非保留
DISTINCT 保留 非保留 保留
DISTRIBUTE 非保留 非保留 非保留
DIV 非保留 非保留 不是关键字
DO 非保留 非保留 非保留
DOUBLE 非保留 非保留 保留
DROP 非保留 非保留 保留
ELSE 保留 非保留 保留
ELSEIF 非保留 非保留 非保留
END 保留 非保留 保留
ESCAPE 保留 非保留 保留
ESCAPED 非保留 非保留 非保留
EVOLUTION 非保留 非保留 非保留
EXCEPT 保留 严格非保留 保留
EXCHANGE 非保留 非保留 非保留
EXCLUDE 非保留 非保留 非保留
EXECUTE 保留 非保留 保留
EXISTS 非保留 非保留 保留
EXIT 非保留 非保留 非保留
EXPLAIN 非保留 非保留 非保留
EXPORT 非保留 非保留 非保留
EXTEND 非保留 非保留 非保留
EXTENDED 非保留 非保留 非保留
EXTERNAL 非保留 非保留 保留
EXTRACT 非保留 非保留 保留
FALSE 保留 非保留 保留
FETCH 保留 非保留 保留
FIELDS 非保留 非保留 非保留
FILTER 保留 非保留 保留
FILEFORMAT 非保留 非保留 非保留
FIRST 非保留 非保留 非保留
FLOAT 非保留 非保留 保留
FOLLOWING 非保留 非保留 非保留
FOR 保留 非保留 保留
FOREIGN 保留 非保留 保留
FORMAT 非保留 非保留 非保留
FORMATTED 非保留 非保留 非保留
FOUND 非保留 非保留 非保留
FROM 保留 非保留 保留
FULL 保留 严格非保留 保留
FUNCTION 非保留 非保留 保留
FUNCTIONS 非保留 非保留 非保留
GENERATED 非保留 非保留 非保留
GLOBAL 非保留 非保留 保留
GRANT 保留 非保留 保留
GROUP 保留 非保留 保留
GROUPING 非保留 非保留 保留
HANDLER 非保留 非保留 非保留
HAVING 保留 非保留 保留
HOUR 非保留 非保留 非保留
HOURS 非保留 非保留 非保留
IDENTIFIER 非保留 非保留 非保留
IDENTITY 非保留 非保留 非保留
IF 非保留 非保留 不是关键字
IGNORE 非保留 非保留 非保留
IMMEDIATE 非保留 非保留 非保留
IMPORT 非保留 非保留 非保留
IN 保留 非保留 保留
INCLUDE 非保留 非保留 非保留
INCREMENT 非保留 非保留 非保留
INDEX 非保留 非保留 非保留
INDEXES 非保留 非保留 非保留
INNER 保留 严格非保留 保留
INPATH 非保留 非保留 非保留
INPUT 非保留 非保留 非保留
INPUTFORMAT 非保留 非保留 非保留
INSERT 非保留 非保留 保留
INT 非保留 非保留 保留
INTEGER 非保留 非保留 保留
INTERSECT 保留 严格非保留 保留
INTERVAL 非保留 非保留 保留
INTO 保留 非保留 保留
INVOKER 非保留 非保留 非保留
IS 保留 非保留 保留
ITEMS 非保留 非保留 非保留
ITERATE 非保留 非保留 非保留
JOIN 保留 严格非保留 保留
JSON 非保留 非保留 非保留
KEYS 非保留 非保留 非保留
LANGUAGE 非保留 非保留 保留
LAST 非保留 非保留 非保留
LATERAL 保留 严格非保留 保留
LAZY 非保留 非保留 非保留
LEADING 保留 非保留 保留
LEAVE 非保留 非保留 非保留
LEFT 保留 严格非保留 保留
LIKE 非保留 非保留 保留
ILIKE 非保留 非保留 非保留
LIMIT 非保留 非保留 非保留
LINES 非保留 非保留 非保留
LIST 非保留 非保留 非保留
LOAD 非保留 非保留 非保留
LOCAL 非保留 非保留 保留
LOCATION 非保留 非保留 非保留
LOCK 非保留 非保留 非保留
LOCKS 非保留 非保留 非保留
LOGICAL 非保留 非保留 非保留
LONG 非保留 非保留 非保留
LOOP 非保留 非保留 非保留
MACRO 非保留 非保留 非保留
MAP 非保留 非保留 非保留
MATCHED 非保留 非保留 非保留
MERGE 非保留 非保留 非保留
MICROSECOND 非保留 非保留 非保留
MICROSECONDS 非保留 非保留 非保留
MILLISECOND 非保留 非保留 非保留
MILLISECONDS 非保留 非保留 非保留
MINUTE 非保留 非保留 非保留
MINUTES 非保留 非保留 非保留
MINUS 非保留 严格非保留 非保留
MODIFIES 非保留 非保留 非保留
MONTH 非保留 非保留 非保留
MONTHS 非保留 非保留 非保留
MSCK 非保留 非保留 非保留
NAME 非保留 非保留 非保留
NAMESPACE 非保留 非保留 非保留
NAMESPACES 非保留 非保留 非保留
NANOSECOND 非保留 非保留 非保留
NANOSECONDS 非保留 非保留 非保留
NATURAL 保留 严格非保留 保留
NO 非保留 非保留 保留
NONE 非保留 非保留 保留
NOT 保留 非保留 保留
NULL 保留 非保留 保留
NULLS 非保留 非保留 非保留
NUMERIC 非保留 非保留 非保留
OF 非保留 非保留 保留
OFFSET 保留 非保留 保留
ON 保留 严格非保留 保留
ONLY 保留 非保留 保留
OPTION 非保留 非保留 非保留
OPTIONS 非保留 非保留 非保留
OR 保留 非保留 保留
ORDER 保留 非保留 保留
OUT 非保留 非保留 保留
OUTER 保留 非保留 保留
OUTPUTFORMAT 非保留 非保留 非保留
OVER 非保留 非保留 非保留
OVERLAPS 保留 非保留 保留
OVERLAY 非保留 非保留 非保留
OVERWRITE 非保留 非保留 非保留
PARTITION 非保留 非保留 保留
PARTITIONED 非保留 非保留 非保留
PARTITIONS 非保留 非保留 非保留
PERCENT 非保留 非保留 非保留
PIVOT 非保留 非保留 非保留
PLACING 非保留 非保留 非保留
POSITION 非保留 非保留 保留
PRECEDING 非保留 非保留 非保留
PRIMARY 保留 非保留 保留
PRINCIPALS 非保留 非保留 非保留
PROPERTIES 非保留 非保留 非保留
PURGE 非保留 非保留 非保留
QUARTER 非保留 非保留 非保留
QUERY 非保留 非保留 非保留
RANGE 非保留 非保留 保留
READS 非保留 非保留 非保留
REAL 非保留 非保留 保留
RECORDREADER 非保留 非保留 非保留
RECORDWRITER 非保留 非保留 非保留
RECOVER 非保留 非保留 非保留
RECURSIVE 保留 非保留 保留
REDUCE 非保留 非保留 非保留
REFERENCES 保留 非保留 保留
REFRESH 非保留 非保留 非保留
REGEXP 非保留 非保留 不是关键字
RENAME 非保留 非保留 非保留
REPAIR 非保留 非保留 非保留
REPEAT 非保留 非保留 非保留
REPEATABLE 非保留 非保留 非保留
REPLACE 非保留 非保留 非保留
RESET 非保留 非保留 非保留
RESPECT 非保留 非保留 非保留
RESTRICT 非保留 非保留 非保留
RETURN 非保留 非保留 保留
RETURNS 非保留 非保留 保留
REVOKE 非保留 非保留 保留
RIGHT 保留 严格非保留 保留
RLIKE 非保留 非保留 非保留
ROLE 非保留 非保留 非保留
ROLES 非保留 非保留 非保留
ROLLBACK 非保留 非保留 保留
ROLLUP 非保留 非保留 保留
ROW 非保留 非保留 保留
ROWS 非保留 非保留 保留
SCHEMA 非保留 非保留 非保留
SCHEMAS 非保留 非保留 非保留
SECOND 非保留 非保留 非保留
SECONDS 非保留 非保留 非保留
SECURITY 非保留 非保留 非保留
SELECT 保留 非保留 保留
SEMI 非保留 严格非保留 非保留
SEPARATED 非保留 非保留 非保留
SERDE 非保留 非保留 非保留
SERDEPROPERTIES 非保留 非保留 非保留
SESSION_USER 保留 非保留 保留
SET 非保留 非保留 保留
SETS 非保留 非保留 非保留
SHORT 非保留 非保留 非保留
SHOW 非保留 非保留 非保留
SINGLE 非保留 非保留 非保留
SKEWED 非保留 非保留 非保留
SMALLINT 非保留 非保留 保留
SOME 保留 非保留 保留
SORT 非保留 非保留 非保留
SORTED 非保留 非保留 非保留
SOURCE 非保留 非保留 非保留
SPECIFIC 非保留 非保留 保留
SQL 保留 非保留 保留
SQLEXCEPTION 非保留 非保留 非保留
SQLSTATE 非保留 非保留 非保留
START 非保留 非保留 保留
STATISTICS 非保留 非保留 非保留
STORED 非保留 非保留 非保留
STRATIFY 非保留 非保留 非保留
STRING 非保留 非保留 非保留
STRUCT 非保留 非保留 非保留
SUBSTR 非保留 非保留 非保留
SUBSTRING 非保留 非保留 非保留
SYNC 非保留 非保留 非保留
SYSTEM_TIME 非保留 非保留 非保留
SYSTEM_VERSION 非保留 非保留 非保留
TABLE 保留 非保留 保留
TABLES 非保留 非保留 非保留
TABLESAMPLE 非保留 非保留 保留
TARGET 非保留 非保留 非保留
TBLPROPERTIES 非保留 非保留 非保留
TEMP 非保留 非保留 不是关键字
TEMPORARY 非保留 非保留 非保留
TERMINATED 非保留 非保留 非保留
THEN 保留 非保留 保留
TIME 保留 非保留 保留
TIMEDIFF 非保留 非保留 非保留
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 非保留 非保留 非保留
UNTIL 非保留 非保留 非保留
UPDATE 非保留 非保留 保留
USE 非保留 非保留 非保留
USER 保留 非保留 保留
USING 保留 严格非保留 保留
VALUE 非保留 非保留 非保留
VALUES 非保留 非保留 保留
VARCHAR 非保留 非保留 保留
VAR 非保留 非保留 非保留
VARIABLE 非保留 非保留 非保留
VARIANT 非保留 非保留 保留
VERSION 非保留 非保留 非保留
VIEW 非保留 非保留 非保留
VIEWS 非保留 非保留 非保留
VOID 非保留 非保留 非保留
WEEK 非保留 非保留 非保留
WEEKS 非保留 非保留 非保留
WHEN 保留 非保留 保留
WHERE 保留 非保留 保留
WHILE 非保留 非保留 非保留
WINDOW 非保留 非保留 保留
WITH 保留 非保留 保留
WITHIN 保留 非保留 保留
X 非保留 非保留 非保留
YEAR 非保留 非保留 非保留
YEARS 非保留 非保留 非保留
ZONE 非保留 非保留 非保留