ANSI 兼容性
在 Spark SQL 中,有两个选项可以遵循 SQL 标准: spark.sql.ansi.enabled
和 spark.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 模式关闭时是允许的
- Numeric <=> Binary
- Date <=> Boolean
- Timestamp <=> Boolean
- Date => Numeric
下表给出了 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
- CAST(Numeric AS Numeric): 如果该值超出目标数据类型的范围,则引发溢出异常。
- CAST(String AS (Numeric/Date/Timestamp/Timestamp_NTZ/Interval/Boolean)): 如果该值无法解析为目标数据类型,则引发运行时异常。
- CAST(Timestamp AS Numeric): 如果自 epoch 以来的秒数超出目标数据类型的范围,则引发溢出异常。
- CAST(Numeric AS Timestamp): 如果数值乘以 1000000(每秒微秒数)超出 Long 类型的范围,则引发溢出异常。
- CAST(Array AS Array): 如果在元素转换中存在任何问题,则引发异常。
- CAST(Map AS Map): 如果在键和值的转换中存在任何问题,则引发异常。
- CAST(Struct AS Struct): 如果在结构字段的转换中存在任何问题,则引发异常。
- CAST(Numeric AS String): 在将 decimal 值转换为字符串时,始终使用纯字符串表示形式,而不是在需要指数时使用科学计数法
- CAST(Interval AS Numeric): 如果日期时间间隔的微秒数或年月间隔的月份数超出目标数据类型的范围,则引发溢出异常。
- CAST(Numeric AS Interval): 如果数值乘以目标间隔的结束单位超出年月间隔的 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|
+---+
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 可以被提升为任何其他类型。
这是优先级列表的图形表示,为一个有向树:
最少通用类型解析
一组类型中的最少通用类型是可以通过该组所有元素的类型从优先级列表中到达的最窄类型。
最少通用类型解析用于:
- 为需要多个参数共享一个参数类型的函数推导参数类型,例如 coalesce、least 或 greatest。
- 为算术运算或比较等运算符推导操作数类型。
- 为 case 表达式等表达式推导结果类型。
- 为数组和映射构造函数推导元素、键或值类型。如果最少通用类型解析为 FLOAT,则应用特殊规则。 对于 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 的函数调用
- 通常,它遵循
Store assignment
规则,即将输入值存储为 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
行为不同的函数
某些 SQL 函数的行为在 ANSI 模式下可能会有所不同 (spark.sql.ansi.enabled=true
)。
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 运算符
某些 SQL 运算符的行为在 ANSI 模式下可能会有所不同 (spark.sql.ansi.enabled=true
)。
array_col[index]
: 如果使用无效索引,此运算符会抛出ArrayIndexOutOfBoundsException
。
ANSI 模式的有用函数
当 ANSI 模式开启时,它会为无效操作抛出异常。您可以使用以下 SQL 函数来抑制此类异常。
try_cast
: 与CAST
相同,不同之处在于,它返回NULL
结果,而不是在运行时错误时抛出异常。try_add
: 与加法运算符+
相同,不同之处在于,它返回NULL
结果,而不是在整数值溢出时抛出异常。try_subtract
: 与加法运算符-
相同,不同之处在于,它返回NULL
结果,而不是在整数值溢出时抛出异常。try_multiply
: 与加法运算符*
相同,不同之处在于,它返回NULL
结果,而不是在整数值溢出时抛出异常。try_divide
: 与除法运算符/
相同,不同之处在于,它返回NULL
结果,而不是在除以 0 时抛出异常。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 | 保留 | 非保留 | 保留 |
主体 | 非保留 | 非保留 | 非保留 |
属性 | 非保留 | 非保留 | 非保留 |
清除 | 非保留 | 非保留 | 非保留 |
季度 | 非保留 | 非保留 | 非保留 |
查询 | 非保留 | 非保留 | 非保留 |
范围 | 非保留 | 非保留 | 保留 |
实数 | 非保留 | 非保留 | 保留 |
记录读取器 | 非保留 | 非保留 | 非保留 |
记录写入器 | 非保留 | 非保留 | 非保留 |
恢复 | 非保留 | 非保留 | 非保留 |
归约 | 非保留 | 非保留 | 非保留 |
引用 | 保留 | 非保留 | 保留 |
刷新 | 非保留 | 非保留 | 非保留 |
正则 | 非保留 | 非保留 | 不是关键字 |
重命名 | 非保留 | 非保留 | 非保留 |
修复 | 非保留 | 非保留 | 非保留 |
可重复的 | 非保留 | 非保留 | 非保留 |
替换 | 非保留 | 非保留 | 非保留 |
重置 | 非保留 | 非保留 | 非保留 |
尊重 | 非保留 | 非保留 | 非保留 |
限制 | 非保留 | 非保留 | 非保留 |
撤销 | 非保留 | 非保留 | 保留 |
右 | 保留 | 严格非保留 | 保留 |
RLIKE (正则LIKE) | 非保留 | 非保留 | 非保留 |
角色 | 非保留 | 非保留 | 非保留 |
角色 | 非保留 | 非保留 | 非保留 |
回滚 | 非保留 | 非保留 | 保留 |
汇总 | 非保留 | 非保留 | 保留 |
行 | 非保留 | 非保留 | 保留 |
行 | 非保留 | 非保留 | 保留 |
模式 | 非保留 | 非保留 | 非保留 |
模式 | 非保留 | 非保留 | 非保留 |
秒 | 非保留 | 非保留 | 非保留 |
秒 | 非保留 | 非保留 | 非保留 |
选择 | 保留 | 非保留 | 保留 |
半 | 非保留 | 严格非保留 | 非保留 |
分隔 | 非保留 | 非保留 | 非保留 |
序列化/反序列化器 | 非保留 | 非保留 | 非保留 |
序列化/反序列化属性 | 非保留 | 非保留 | 非保留 |
会话用户 | 保留 | 非保留 | 保留 |
设置 | 非保留 | 非保留 | 保留 |
集合 | 非保留 | 非保留 | 非保留 |
短整型 | 非保留 | 非保留 | 非保留 |
显示 | 非保留 | 非保留 | 非保留 |
倾斜 | 非保留 | 非保留 | 非保留 |
小整数 | 非保留 | 非保留 | 保留 |
一些 | 保留 | 非保留 | 保留 |
排序 | 非保留 | 非保留 | 非保留 |
已排序 | 非保留 | 非保留 | 非保留 |
源 | 非保留 | 非保留 | 非保留 |
开始 | 非保留 | 非保留 | 保留 |
统计信息 | 非保留 | 非保留 | 非保留 |
存储 | 非保留 | 非保留 | 非保留 |
分层 | 非保留 | 非保留 | 非保留 |
字符串 | 非保留 | 非保留 | 非保留 |
结构体 | 非保留 | 非保留 | 非保留 |
子串 | 非保留 | 非保留 | 非保留 |
子字符串 | 非保留 | 非保留 | 非保留 |
同步 | 非保留 | 非保留 | 非保留 |
系统时间 | 非保留 | 非保留 | 非保留 |
系统版本 | 非保留 | 非保留 | 非保留 |
表 | 保留 | 非保留 | 保留 |
表 | 非保留 | 非保留 | 非保留 |
表抽样 | 非保留 | 非保留 | 保留 |
目标 | 非保留 | 非保留 | 非保留 |
表属性 | 非保留 | 非保留 | 非保留 |
临时 | 非保留 | 非保留 | 不是关键字 |
临时的 | 非保留 | 非保留 | 非保留 |
终止 | 非保留 | 非保留 | 非保留 |
那么 | 保留 | 非保留 | 保留 |
时间 | 保留 | 非保留 | 保留 |
时间戳 | 非保留 | 非保留 | 非保留 |
时间戳_LTZ (带时区的时间戳) | 非保留 | 非保留 | 非保留 |
时间戳_NTZ (不带时区的时间戳) | 非保留 | 非保留 | 非保留 |
时间戳增加 | 非保留 | 非保留 | 非保留 |
时间戳差异 | 非保留 | 非保留 | 非保留 |
微整型 | 非保留 | 非保留 | 非保留 |
到 | 保留 | 非保留 | 保留 |
触摸 | 非保留 | 非保留 | 非保留 |
尾随 | 保留 | 非保留 | 保留 |
事务 | 非保留 | 非保留 | 非保留 |
事务 | 非保留 | 非保留 | 非保留 |
转换 | 非保留 | 非保留 | 非保留 |
修剪 | 非保留 | 非保留 | 非保留 |
真 | 非保留 | 非保留 | 保留 |
截断 | 非保留 | 非保留 | 保留 |
尝试转换 | 非保留 | 非保留 | 非保留 |
类型 | 非保留 | 非保留 | 非保留 |
解压 | 非保留 | 非保留 | 非保留 |
无界 | 非保留 | 非保留 | 非保留 |
取消缓存 | 非保留 | 非保留 | 非保留 |
联合 | 保留 | 严格非保留 | 保留 |
唯一 | 保留 | 非保留 | 保留 |
未知 | 保留 | 非保留 | 保留 |
解锁 | 非保留 | 非保留 | 非保留 |
取消透视 | 非保留 | 非保留 | 非保留 |
取消设置 | 非保留 | 非保留 | 非保留 |
更新 | 非保留 | 非保留 | 保留 |
使用 | 非保留 | 非保留 | 非保留 |
用户 | 保留 | 非保留 | 保留 |
使用 | 保留 | 严格非保留 | 保留 |
值 | 非保留 | 非保留 | 保留 |
变长字符串 | 非保留 | 非保留 | 保留 |
版本 | 非保留 | 非保留 | 非保留 |
视图 | 非保留 | 非保留 | 非保留 |
视图 | 非保留 | 非保留 | 非保留 |
空 | 非保留 | 非保留 | 非保留 |
周 | 非保留 | 非保留 | 非保留 |
周 | 非保留 | 非保留 | 非保留 |
当 | 保留 | 非保留 | 保留 |
哪里 | 保留 | 非保留 | 保留 |
窗口 | 非保留 | 非保留 | 保留 |
与 | 保留 | 非保留 | 保留 |
在...之内 | 保留 | 非保留 | 保留 |
X | 非保留 | 非保留 | 非保留 |
年 | 非保留 | 非保留 | 非保留 |
年 | 非保留 | 非保留 | 非保留 |
时区 | 非保留 | 非保留 | 非保留 |