ANSI 兼容性

在 Spark SQL 中,有两个选项可以遵循 SQL 标准: spark.sql.ansi.enabledspark.sql.storeAssignmentPolicy(详细信息请参见下表)。

spark.sql.ansi.enabled 设置为 true 时,Spark SQL 使用符合 ANSI 的方言,而不是符合 Hive 的方言。 例如,如果 SQL 运算符/函数的输入无效,Spark 将在运行时抛出异常,而不是返回 null 结果。 某些 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 大致相同。 它不允许某些不合理的类型转换,例如将字符串转换为 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 中,默认情况下不会检查对数值类型(decimal 除外)执行的算术运算是否溢出。 这意味着,如果某个操作导致溢出,则结果与 Java/Scala 程序中的相应操作相同(例如,如果 2 个整数的和高于可表示的最大值,则结果为负数)。 另一方面,Spark SQL 为 decimal 溢出返回 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”表示该组合无效。

源\目标 Numeric String Date Timestamp Timestamp_NTZ Interval Boolean Binary Array Map Struct
Numeric Y Y N Y N Y Y N N N N
String Y Y Y Y Y Y Y Y N N N
Date N Y Y Y Y N N N N N N
Timestamp Y Y Y Y Y N N N N N N
Timestamp_NTZ N Y Y Y Y N N N N N N
Interval Y Y N N N Y N N N N N
Boolean Y Y N N N N Y N N N N
Binary N Y N N N N N Y N N N
Array 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`
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|
+---+

Cast 中的舍入

当将带有小数部分的 decimal 转换为以 SECOND 作为结束单位的间隔类型时,如 INTERVAL HOUR TO SECOND,Spark 将小数部分向“最近的邻居”舍入,除非两个邻居等距,在这种情况下向上舍入。

存储分配

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

源\目标 Numeric String Date Timestamp Timestamp_NTZ Interval Boolean Binary Array Map Struct
Numeric Y Y N N N N N N N N N
String N Y N N N N N N N N N
Date N Y Y Y Y N N N N N N
Timestamp N Y Y Y Y N N N N N N
Timestamp_NTZ N Y Y Y Y N N N N N N
Interval N Y N N N N* N N N N N
Boolean N Y N N N N Y N N N N
Binary N Y N N N N N Y N N N
Array 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 不支持 interval 类型表列。

** 对于 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 Date -> Timestamp_NTZ -> Timestamp
Timestamp Timestamp
String String, Long -> Double, Date -> Timestamp_NTZ -> Timestamp , Boolean, Binary **
Binary Binary
Boolean Boolean
Interval Interval
Map Map***
Array Array***
Struct Struct***

* 为了避免精度损失,最少通用类型解析会跳过 float 类型。

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

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

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

这是优先级列表的图形表示,为一个有向树: Type Precedence List

最少通用类型解析

一组类型中的最少通用类型是可以通过该组所有元素的类型从优先级列表中到达的最窄类型。

最少通用类型解析用于:

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

行为不同的函数

某些 SQL 函数的行为在 ANSI 模式下可能会有所不同 (spark.sql.ansi.enabled=true)。

SQL 运算符

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

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 保留 非保留 保留
主体 非保留 非保留 非保留
属性 非保留 非保留 非保留
清除 非保留 非保留 非保留
季度 非保留 非保留 非保留
查询 非保留 非保留 非保留
范围 非保留 非保留 保留
实数 非保留 非保留 保留
记录读取器 非保留 非保留 非保留
记录写入器 非保留 非保留 非保留
恢复 非保留 非保留 非保留
归约 非保留 非保留 非保留
引用 保留 非保留 保留
刷新 非保留 非保留 非保留
正则 非保留 非保留 不是关键字
重命名 非保留 非保留 非保留
修复 非保留 非保留 非保留
可重复的 非保留 非保留 非保留
替换 非保留 非保留 非保留
重置 非保留 非保留 非保留
尊重 非保留 非保留 非保留
限制 非保留 非保留 非保留
撤销 非保留 非保留 保留
保留 严格非保留 保留
RLIKE (正则LIKE) 非保留 非保留 非保留
角色 非保留 非保留 非保留
角色 非保留 非保留 非保留
回滚 非保留 非保留 保留
汇总 非保留 非保留 保留
非保留 非保留 保留
非保留 非保留 保留
模式 非保留 非保留 非保留
模式 非保留 非保留 非保留
非保留 非保留 非保留
非保留 非保留 非保留
选择 保留 非保留 保留
非保留 严格非保留 非保留
分隔 非保留 非保留 非保留
序列化/反序列化器 非保留 非保留 非保留
序列化/反序列化属性 非保留 非保留 非保留
会话用户 保留 非保留 保留
设置 非保留 非保留 保留
集合 非保留 非保留 非保留
短整型 非保留 非保留 非保留
显示 非保留 非保留 非保留
倾斜 非保留 非保留 非保留
小整数 非保留 非保留 保留
一些 保留 非保留 保留
排序 非保留 非保留 非保留
已排序 非保留 非保留 非保留
非保留 非保留 非保留
开始 非保留 非保留 保留
统计信息 非保留 非保留 非保留
存储 非保留 非保留 非保留
分层 非保留 非保留 非保留
字符串 非保留 非保留 非保留
结构体 非保留 非保留 非保留
子串 非保留 非保留 非保留
子字符串 非保留 非保留 非保留
同步 非保留 非保留 非保留
系统时间 非保留 非保留 非保留
系统版本 非保留 非保留 非保留
保留 非保留 保留
非保留 非保留 非保留
表抽样 非保留 非保留 保留
目标 非保留 非保留 非保留
表属性 非保留 非保留 非保留
临时 非保留 非保留 不是关键字
临时的 非保留 非保留 非保留
终止 非保留 非保留 非保留
那么 保留 非保留 保留
时间 保留 非保留 保留
时间戳 非保留 非保留 非保留
时间戳_LTZ (带时区的时间戳) 非保留 非保留 非保留
时间戳_NTZ (不带时区的时间戳) 非保留 非保留 非保留
时间戳增加 非保留 非保留 非保留
时间戳差异 非保留 非保留 非保留
微整型 非保留 非保留 非保留
保留 非保留 保留
触摸 非保留 非保留 非保留
尾随 保留 非保留 保留
事务 非保留 非保留 非保留
事务 非保留 非保留 非保留
转换 非保留 非保留 非保留
修剪 非保留 非保留 非保留
非保留 非保留 保留
截断 非保留 非保留 保留
尝试转换 非保留 非保留 非保留
类型 非保留 非保留 非保留
解压 非保留 非保留 非保留
无界 非保留 非保留 非保留
取消缓存 非保留 非保留 非保留
联合 保留 严格非保留 保留
唯一 保留 非保留 保留
未知 保留 非保留 保留
解锁 非保留 非保留 非保留
取消透视 非保留 非保留 非保留
取消设置 非保留 非保留 非保留
更新 非保留 非保留 保留
使用 非保留 非保留 非保留
用户 保留 非保留 保留
使用 保留 严格非保留 保留
非保留 非保留 保留
变长字符串 非保留 非保留 保留
版本 非保留 非保留 非保留
视图 非保留 非保留 非保留
视图 非保留 非保留 非保留
非保留 非保留 非保留
非保留 非保留 非保留
非保留 非保留 非保留
保留 非保留 保留
哪里 保留 非保留 保留
窗口 非保留 非保留 保留
保留 非保留 保留
在...之内 保留 非保留 保留
X 非保留 非保留 非保留
非保留 非保留 非保留
非保留 非保留 非保留
时区 非保留 非保留 非保留