Databricks Runtime 中的 ANSI 合規性

適用於:check marked yes Databricks Runtime

本文說明 Databricks Runtime 中的 ANSI 合規性。 如需 Databricks SQL 中的 ANSI 模式,請參閱 ANSI_MODE

Spark SQL 有兩個選項可支援符合 ANSI SQL 標準: spark.sql.ansi.enabledspark.sql.storeAssignmentPolicy

當 設定為 truespark.sql.ansi.enabled,Spark SQL 會使用 ANSI 相容的方言,而不是符合 Hive 規範。 例如,如果 SQL 運算符/函式的輸入無效,Spark 會在運行時間擲回例外狀況,而不是傳回 Null 結果。 某些 ANSI 方言功能可能不是直接從 ANSI SQL 標準,但其行為會與 ANSI SQL 的樣式一致。

此外,Spark SQL 有獨立的選項,可在數據表中儲存數據列時控制隱含轉換行為。 轉換行為會定義為標準中的存放區指派規則。

當 設定為 ANSIspark.sql.storeAssignmentPolicy,Spark SQL 符合 ANSI 存放區指派規則。 這是個別的組態,因為它的預設值是 ANSI,而預設會停用組態 spark.sql.ansi.enabled

下表摘要說明行為:

屬性名稱 預設 意義
spark.sql.ansi.enabled false 若為 true,Spark 會嘗試符合 ANSI SQL 規格:

* 如果在整數或十進位字段的任何作業中發生溢位,則會擲回運行時間例外狀況。
* 禁止使用 ANSI SQL 的保留關鍵字作為 SQL 剖析器中的識別碼。
spark.sql.storeAssignmentPolicy ANSI 將值儲存至具有不同數據類型的數據行時,Spark 會執行類型轉換。 類型強制規則有三個原則: ANSIlegacystrict

* ANSI:Spark 會根據 ANSI SQL 執行類型強制。 實際上,行為大多與 PostgreSQL 相同。 它不允許某些不合理的類型轉換,例如將字串轉換成 int 或 double 轉換為布爾值。
* legacy:只要Spark是有效的Cast,Spark就會允許類型強制轉換,這是非常鬆散的。 例如,允許將字串轉換成 int 或 double 轉換為布爾值。 這也是Spark 2.x 中唯一的行為,而且與Hive相容。
* strict:Spark 不允許在類型強制中發生任何可能的精確度遺失或數據截斷,例如,不允許將 double 轉換成 int 或 decimal 到 double。

下列小節會在啟用 ANSI 模式時,呈現算術運算、類型轉換和 SQL 剖析的行為變更。 針對Spark SQL中的類型轉換,有三種類型,本文會逐一介紹它們:轉換、儲存指派和類型強制。

算術運算

在Spark SQL中,在數值類型上執行的算術運算預設不會檢查是否有溢位。 這表示如果作業造成溢位,則結果與 Java 或 Scala 程式中對應的作業相同(例如,如果 2 個整數的總和高於可表示的最大值,則結果為負數)。 另一方面,Spark SQL 會針對十進位溢位傳回 Null。 當 spark.sql.ansi.enabled 設定為 true 且溢位發生在數值和間隔算術運算中時,它會在運行時間擲回算術例外狀況。

-- `spark.sql.ansi.enabled=true`
> SELECT 2147483647 + 1;
 error: integer overflow

-- `spark.sql.ansi.enabled=false`
> SELECT 2147483647 + 1;
  -2147483648

Cast

當 設為 truespark.sql.ansi.enabled,語法的CAST明確轉換會針對標準中定義的非法轉換模式擲回運行時間例外狀況,例如從字串轉換成整數。

CAST Spark ANSI 模式的 子句遵循 ISO/IEC 9075-2:2011 資訊技術 - 資料庫語言 - SQL - 第 2 部分:Foundation (SQL/Foundation)的第 6.13 節「轉換規格」語法規則,但特別允許根據 ANSI 標準不允許下列直接類型轉換:

  • NumericType <=> BooleanType
  • StringType <=> BinaryType

下表提供表達式中 CAST 來源和目標數據類型的有效組合。 “Y” 表示組合在語法上有效且沒有限制,而 “N” 表示組合無效。

SourceTarget 數值 String Date 時間戳記 間隔 布林值 二進位 陣列 地圖 結構
數值 Y Y N N N Y N N N N
String Y Y Y Y Y Y Y N N N
Date Y Y N N N N N N
時間戳記 Y Y N N N N N N
間隔 Y N N Y N N N N N
布林值 Y Y N N N Y N N N N
二進位 N N N N N Y N N N
陣列 N N N N N N N Y N N
地圖 N N N N N N N N Y
結構 N N N N N N N N N
-- Examples of explicit casting

-- `spark.sql.ansi.enabled=true`
> SELECT CAST('a' AS INT);
  ERROR: [CAST_INVALID_INPUT] The value 'a' of the type "STRING" cannot be cast to "INT" because it is malformed.

> SELECT CAST(2147483648L AS INT);
  ERROR: [CAST_OVERFLOW] The value 2147483648L of the type "BIGINT" cannot be cast to "INT" due to an overflow.

> SELECT CAST(DATE'2020-01-01' AS INT)
  ERROR: [DATATYPE_MISMATCH.CAST_WITH_FUNC_SUGGESTION] Cannot resolve "CAST(DATE '2020-01-01' AS INT)" due to data type mismatch: cannot cast "DATE" to "INT".

-- `spark.sql.ansi.enabled=false` (This is a default behavior)
> SELECT cast('a' AS INT);
  null

> SELECT CAST(2147483648L AS INT);
  -2147483648

> SELECT CAST(DATE'2020-01-01' AS INT);
  null

市集指派

設定 spark.sql.storeAssignmentPolicy 預設為 ANSI。 使用此設定時,當來源值的數據類型不符合目標數據行類型時,Spark SQL 會自動將 ANSI CAST 子句新增至 INSERT 語句。 在此原則下插入數據表期間,Spark 會檢查並拒絕無效的轉換,並擲回例外狀況以確保數據品質。 這表示如果插入嘗試因類型不符而失敗,則不會造成任何部分寫入數據表的數據。

範例:

-- spark.sql.storeAssignmentPolicy=ANSI
> CREATE TABLE test(i INT);
> INSERT INTO test VALUES (2147483648L);
  ERROR: [CAST_OVERFLOW_IN_TABLE_INSERT] Fail to insert a value of "BIGINT" type into the "INT" type column `i` due to an overflow.

> INSERT INTO test VALUES ('a');
  ERROR: [CAST_INVALID_INPUT ERROR] The value 'a' of the type "STRING" cannot be cast to "INT" because it is malformed

這些範例顯示 Spark SQL 防止插入不相容的數據,進而維護數據完整性。

spark.sql.storeAssignmentPolicy當 設定為 LEGACY時,Spark SQL 會還原為最多 Spark 2.x 的行為。 在此模式中,它不使用 ANSI CAST,而是會套用舊版 CAST 作業。 在此原則下,數據表插入期間無效的轉換會導致 NULL 值或插入不正確的值,而不是擲回例外狀況。 範例:

-- spark.sql.storeAssignmentPolicy=LEGACY
> CREATE TABLE test(i INT);
> INSERT INTO test VALUES (2147483648L);
> INSERT INTO test VALUES ('a');
> SELECT * FROM test;

-- Results
--  -2147483648 (incorrect value due to overflow)
--  null (cannot cast 'a' to INT)

類型強制

類型升級和優先順序

當 設定為 truespark.sql.ansi.enabled,Spark SQL 會使用數個規則來管理數據類型之間的衝突解析方式。 此衝突解決的核心是類型優先順序清單,其會定義指定的數據類型值是否可以隱含地升階為另一個數據類型。

資料類型 優先順序清單(從最窄到最寬)
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 十進制 -> Float* -> Double
Float Float -> Double
Double 雙重
Date 日期 -> 時間戳
時間戳記 時間戳記
String String
Binary Binary
Boolean Boolean
間隔 間隔
地圖 地圖**
陣列 陣 列**
結構 結構**
  • 略過最不常見的類型解析浮點數,以避免遺失精確度。

** 對於複雜類型,優先順序規則會以遞歸方式套用至其元件元素。

特殊規則適用於 String 類型和不具類型的 NULL。 NULL 可以升階為任何其他類型,而 String 可以升級為任何簡單的數據類型。

這是以導向樹狀結構表示的優先順序清單圖形描述: Graphical representation of precedence rules

最不常見的類型解析

一組型別中最不常見的類型是可從優先順序清單觸達的最窄型別,由一組型別的所有元素。

最不常見的類型解析是用來:

  • 決定是否可以使用較窄型別的自變數來叫用預期型別參數的函式。
  • 衍生函式的自變數類型,這些函式預期有多個參數的共用自變數類型,例如聯合、最小或最大。
  • 衍生運算子的操作數類型,例如算術運算或比較。
  • 衍生案例表達式等表達式的結果類型。
  • 衍生數位和對應建構函式的專案、索引鍵或實值型別。

如果最不常見的類型解析為 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

-- The substring function expects arguments of type INT for the start and length parameters.
> SELECT substring('hello', 1Y, 2);
he

> SELECT substring('hello', '1', 2);
he

> SELECT substring('hello', 1L, 2);
Error: Argument 2 requires an INT type.

> SELECT substring('hello', str, 2) FROM VALUES(CAST('1' AS STRING)) AS T(str);
Error: Argument 2 requires an INT type.

SQL 函式

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

  • size:此函式會針對 ANSI 模式下的 Null 輸入傳回 null。
  • element_at:
    • 如果使用無效的索引,則此函式會 ArrayIndexOutOfBoundsException 擲回。
    • 如果對應中沒有索引鍵,則此函式會 NoSuchElementException 擲回 。
  • elt:如果使用無效的索引,此函式會 ArrayIndexOutOfBoundsException 擲回。
  • make_date:如果結果日期無效,此函式會失敗,但例外狀況。
  • make_timestamp:如果結果時間戳無效,此函式會失敗,併發生例外狀況。
  • make_interval:如果結果間隔無效,此函式會失敗,並出現例外狀況。
  • next_day:如果輸入不是有效的星期幾,則此函式會 IllegalArgumentException 擲回。
  • parse_url:如果輸入字串不是有效的 URL,此函式會 IllegalArgumentException 擲回。
  • to_date:如果無法剖析輸入字串,或模式字串無效,則此函式會失敗併發生例外狀況。
  • to_timestamp:如果無法剖析輸入字串,或模式字串無效,則此函式會失敗併發生例外狀況。
  • to_unix_timestamp:如果無法剖析輸入字串,或模式字串無效,則此函式會失敗併發生例外狀況。
  • unix_timestamp:如果無法剖析輸入字串,或模式字串無效,則此函式會失敗併發生例外狀況。

SQL 運算子

某些 SQL 運算子的行為在 ANSI 模式下可能不同(spark.sql.ansi.enabled=true)。

  • array_col[index]:如果使用無效的索引,這個運算符會 ArrayIndexOutOfBoundsException 擲回。
  • map_col[key]:如果對應中沒有索引鍵,這個運算子會 NoSuchElementException 擲回 。
  • CAST(string_col AS TIMESTAMP):如果無法剖析輸入字串,這個運算符就會失敗,併發生例外狀況。
  • CAST(string_col AS DATE):如果無法剖析輸入字串,這個運算符就會失敗,併發生例外狀況。

ANSI 模式的實用函式

當 ANSI 模式開啟時,它會擲回無效作業的例外狀況。 您可以使用下列 SQL 函式來隱藏這類例外狀況。

  • try_cast:與 CAST相同,不同之處在於它會傳 NULL 回結果,而不是在運行時間錯誤時擲回例外狀況。
  • try_add:與 add 運算符 +相同,不同之處在於它會傳 NULL 回結果,而不是在整數值溢位上擲回例外狀況。
  • try_divide:與除法運算符 /相同,不同之處在於它會傳 NULL 回結果,而不是在除法 0 上擲回例外狀況。

SQL 關鍵詞

當 為 true 時 spark.sql.ansi.enabled ,Spark SQL 會使用 ANSI 模式剖析器。 在此模式中,Spark SQL 有兩種關鍵詞:

  • 保留關鍵詞:保留且不能做為數據表、檢視表、數據行、函式、別名等標識碼的關鍵詞。
  • 非保留關鍵詞:只有特定內容中具有特殊意義的關鍵詞,而且可作為其他內容中的標識符。 例如, EXPLAIN SELECT ... 是命令,但EXPLAIN可以做為其他地方的標識碼。

停用 ANSI 模式時,Spark SQL 有兩種關鍵詞:

  • 非保留關鍵詞:啟用 ANSI 模式時的相同定義。
  • Strict-non-reserved 關鍵詞:非保留關鍵詞的嚴格版本,不能當做數據表別名使用。

spark.sql.ansi.enabled默認為 false。

以下是Spark SQL 中所有關鍵詞的清單。

關鍵字 Spark SQL ANSI 模式 Spark SQL 預設模式 SQL-2016
ADD 非保留 非保留 非保留
AFTER 非保留 非保留 非保留
ALL 保留 非保留 保留
ALTER 非保留 非保留 保留
總是 非保留 非保留 非保留
ANALYZE 非保留 非保留 非保留
保留 非保留 保留
非保留 strict-non-reserved 非保留
ANY 保留 非保留 保留
檔案 非保留 非保留 非保留
ARRAY 非保留 非保留 保留
AS 保留 非保留 保留
ASC 非保留 非保留 非保留
AT 非保留 非保留 保留
AUTHORIZATION 保留 非保留 保留
BETWEEN 非保留 非保留 保留
BOTH 保留 非保留 保留
非保留 非保留 非保留
非保留 非保留 非保留
BY 非保留 非保留 保留
CACHE 非保留 非保留 非保留
CASCADE 非保留 非保留 非保留
CASE 保留 非保留 保留
CAST 保留 非保留 保留
變更 非保留 非保留 非保留
CHECK 保留 非保留 保留
CLEAR 非保留 非保留 非保留
集群 非保留 非保留 非保留
CLUSTERED 非保留 非保留 非保留
CODEGEN 非保留 非保留 非保留
COLLATE 保留 非保留 保留
COLLECTION 非保留 非保留 非保留
COLUMN 保留 非保留 保留
COLUMNS 非保留 非保留 非保留
COMMENT 非保留 非保留 非保留
COMMIT 非保留 非保留 保留
緊湊 非保留 非保留 非保留
COMPACTIONS 非保留 非保留 非保留
COMPUTE 非保留 非保留 非保留
CONCATENATE 非保留 非保留 非保留
CONSTRAINT 保留 非保留 保留
成本 非保留 非保留 非保留
CREATE 保留 非保留 保留
CROSS 保留 strict-non-reserved 保留
CUBE 非保留 非保留 保留
CURRENT 非保留 非保留 保留
CURRENT_DATE 保留 非保留 保留
CURRENT_TIME 保留 非保留 保留
CURRENT_TIMESTAMP 保留 非保留 保留
CURRENT_USER 保留 非保留 保留
資料 非保留 非保留 非保留
DATABASE 非保留 非保留 非保留
資料庫 非保留 非保留 非保留
DAY 非保留 非保留 非保留
DBPROPERTIES 非保留 非保留 非保留
定義 非保留 非保留 非保留
DELETE 非保留 非保留 保留
分隔 非保留 非保留 非保留
DESC 非保留 非保留 非保留
DESCRIBE 非保留 非保留 保留
DFS 非保留 非保留 非保留
目錄 非保留 非保留 非保留
目錄 非保留 非保留 非保留
DISTINCT 保留 非保留 保留
分發 非保留 非保留 非保留
Div 非保留 非保留 不是關鍵詞
DROP 非保留 非保留 保留
ELSE 保留 非保留 保留
END 保留 非保留 保留
ESCAPE 保留 非保留 保留
逃脫 非保留 非保留 非保留
EXCEPT 保留 strict-non-reserved 保留
交換 非保留 非保留 非保留
EXISTS 非保留 非保留 保留
EXPLAIN 非保留 非保留 非保留
出口 非保留 非保留 非保留
延伸 非保留 非保留 非保留
EXTERNAL 非保留 非保留 保留
EXTRACT 非保留 非保留 保留
FALSE 保留 非保留 保留
FETCH 保留 非保留 保留
欄位 非保留 非保留 非保留
FILTER 保留 非保留 保留
FILEFORMAT 非保留 非保留 非保留
FIRST 非保留 非保留 非保留
FN 非保留 非保留 非保留
以下 非保留 非保留 非保留
FOR 保留 非保留 保留
FOREIGN 保留 非保留 保留
FORMAT 非保留 非保留 非保留
格式化 非保留 非保留 非保留
FROM 保留 非保留 保留
FULL 保留 strict-non-reserved 保留
FUNCTION 非保留 非保留 保留
函式 非保留 非保留 非保留
GENERATED 非保留 非保留 非保留
GLOBAL 非保留 非保留 保留
GRANT 保留 非保留 保留
撥款 非保留 非保留 非保留
GROUP 保留 非保留 保留
GROUPING 非保留 非保留 保留
HAVING 保留 非保留 保留
HOUR 非保留 非保留 非保留
IF 非保留 非保留 不是關鍵詞
IGNORE 非保留 非保留 非保留
匯入 非保留 非保留 非保留
IN 保留 非保留 保留
INDEX 非保留 非保留 非保留
指標 非保留 非保留 非保留
INNER 保留 strict-non-reserved 保留
INPATH 非保留 非保留 非保留
INPUTFORMAT 非保留 非保留 非保留
INSERT 非保留 非保留 保留
INTERSECT 保留 strict-non-reserved 保留
INTERVAL 非保留 非保留 保留
INTO 保留 非保留 保留
IS 保留 非保留 保留
專案 非保留 非保留 非保留
JOIN 保留 strict-non-reserved 保留
KEY 非保留 非保留 非保留
金鑰 非保留 非保留 非保留
LAST 非保留 非保留 非保留
LATERAL 保留 strict-non-reserved 保留
懶惰 非保留 非保留 非保留
LEADING 保留 非保留 保留
LEFT 保留 strict-non-reserved 保留
LIKE 非保留 非保留 保留
ILIKE 非保留 非保留 非保留
LIMIT 非保留 非保留 非保留
非保留 非保留 非保留
清單 非保留 非保留 非保留
LOAD 非保留 非保留 非保留
LOCAL 非保留 非保留 保留
LOCATION 非保留 非保留 非保留
LOCK 非保留 非保留 非保留
非保留 非保留 非保留
LOGICAL 非保留 非保留 非保留
MACRO 非保留 非保留 非保留
MAP 非保留 非保留 非保留
匹配 非保留 非保留 非保留
MERGE 非保留 非保留 非保留
MINUTE 非保留 非保留 非保留
減去 非保留 strict-non-reserved 非保留
MONTH 非保留 非保留 非保留
MSCK 非保留 非保留 非保留
命名空間 非保留 非保留 非保留
命名空間 非保留 非保留 非保留
NATURAL 保留 strict-non-reserved 保留
非保留 非保留 保留
NOT 保留 非保留 保留
NULL 保留 非保留 保留
NULLS 非保留 非保留 非保留
OF 非保留 非保留 保留
ON 保留 strict-non-reserved 保留
ONLY 保留 非保留 保留
OPTION 非保留 非保留 非保留
OPTIONS 非保留 非保留 非保留
OR 保留 非保留 保留
ORDER 保留 非保留 保留
OUT 非保留 非保留 保留
OUTER 保留 非保留 保留
OUTPUTFORMAT 非保留 非保留 非保留
OVER 非保留 非保留 非保留
OVERLAPS 保留 非保留 保留
OVERLAY 非保留 非保留 非保留
覆蓋 非保留 非保留 非保留
PARTITION 非保留 非保留 保留
PARTITIONED 非保留 非保留 非保留
磁碟分割 非保留 非保留 非保留
PERCENT 非保留 非保留 非保留
PIVOT 非保留 非保留 非保留
放置 非保留 非保留 非保留
POSITION 非保留 非保留 保留
非保留 非保留 非保留
PRIMARY 保留 非保留 保留
校長 非保留 非保留 非保留
屬性 非保留 非保留 非保留
PURGE 非保留 非保留 非保留
資格 保留 非保留 保留
QUERY 非保留 非保留 非保留
RANGE 非保留 非保留 保留
收件者 非保留 非保留 非保留
收件者 非保留 非保留 非保留
RECORDREADER 非保留 非保留 非保留
RECORDWRITER 非保留 非保留 非保留
恢復 非保留 非保留 非保留
REDUCE 非保留 非保留 非保留
REFERENCES 保留 非保留 保留
REFRESH 非保留 非保留 非保留
Regexp 非保留 非保留 不是關鍵詞
移除 非保留 非保留 非保留
RENAME 非保留 非保留 非保留
REPAIR 非保留 非保留 非保留
REPLACE 非保留 非保留 非保留
RESET 非保留 非保留 非保留
尊重 非保留 非保留 非保留
RESTRICT 非保留 非保留 非保留
REVOKE 非保留 非保留 保留
RIGHT 保留 strict-non-reserved 保留
RLIKE 非保留 非保留 非保留
ROLE 非保留 非保留 非保留
角色 非保留 非保留 非保留
ROLLBACK 非保留 非保留 保留
ROLLUP 非保留 非保留 保留
ROW 非保留 非保留 保留
ROWS 非保留 非保留 保留
SCHEMA 非保留 非保留 非保留
結構描述 非保留 非保留 不是關鍵詞
SECOND 非保留 非保留 非保留
SELECT 保留 非保留 保留
非保留 strict-non-reserved 非保留
分開 非保留 非保留 非保留
SERDE 非保留 非保留 非保留
SERDEPROPERTIES 非保留 非保留 非保留
SESSION_USER 保留 非保留 保留
SET 非保留 非保留 保留
SETS 非保留 非保留 非保留
SHARE 非保留 非保留 非保留
共用 非保留 非保留 非保留
顯示 非保留 非保留 非保留
扭曲 非保留 非保留 非保留
SOME 保留 非保留 保留
排序 非保留 非保留 非保留
排序 非保留 非保留 非保留
START 非保留 非保留 保留
STATISTICS 非保留 非保留 非保留
存儲 非保留 非保留 非保留
分層 非保留 非保留 非保留
STRUCT 非保留 非保留 非保留
SUBSTR 非保留 非保留 非保留
SUBSTRING 非保留 非保留 非保留
同步 非保留 非保留 非保留
TABLE 保留 非保留 保留
TABLES 非保留 非保留 非保留
TABLESAMPLE 非保留 非保留 保留
TBLPROPERTIES 非保留 非保留 非保留
臨時 非保留 非保留 不是關鍵詞
TEMPORARY 非保留 非保留 非保留
終止 非保留 非保留 非保留
THEN 保留 非保留 保留
TIME 保留 非保留 保留
收件人 保留 非保留 保留
觸摸 非保留 非保留 非保留
TRAILING 保留 非保留 保留
TRANSACTION 非保留 非保留 非保留
交易 非保留 非保留 非保留
TRANSFORM 非保留 非保留 非保留
TRIM 非保留 非保留 非保留
TRUE 非保留 非保留 保留
TRUNCATE 非保留 非保留 保留
TRY_CAST 非保留 非保留 非保留
TYPE 非保留 非保留 非保留
UNARCHIVE 非保留 非保留 非保留
無限 非保留 非保留 非保留
UNCACHE 非保留 非保留 非保留
UNION 保留 strict-non-reserved 保留
UNIQUE 保留 非保留 保留
UNKNOWN 保留 非保留 保留
UNLOCK 非保留 非保留 非保留
UNSET 非保留 非保留 非保留
UPDATE 非保留 非保留 保留
USE 非保留 非保留 非保留
USER 保留 非保留 保留
USING 保留 strict-non-reserved 保留
VALUES 非保留 非保留 保留
VIEW 非保留 非保留 非保留
VIEWS 非保留 非保留 非保留
WHEN 保留 非保留 保留
WHERE 保留 非保留 保留
WINDOW 非保留 非保留 保留
WITH 保留 非保留 保留
YEAR 非保留 非保留 非保留
ZONE 非保留 非保留 非保留