ANSI 兼容性

在 Spark SQL 中,有两个选项可以与 SQL 标准兼容:spark.sql.ansi.enabledspark.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

-- 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 可以提升为任何其他类型。

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

最小公倍数解析

一组类型中的最小公倍数是从优先级列表中所有类型集元素都可达到的最窄类型。

最小公倍数解析用于

-- 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.enabledspark.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 非保留 非保留 非保留