文件首頁
MySQL 9.0 參考手冊
相關文件 下載本手冊
PDF (US Ltr) - 40.0Mb
PDF (A4) - 40.1Mb
Man Pages (TGZ) - 258.2Kb
Man Pages (Zip) - 365.3Kb
Info (Gzip) - 4.0Mb
Info (Zip) - 4.0Mb


15.1.20.10 隱形欄位

MySQL 9.0 支援隱形欄位。隱形欄位通常對查詢是隱藏的,但如果明確參照,則可以存取。

作為隱形欄位何時有用的說明,假設一個應用程式使用 SELECT * 查詢來存取資料表,並且即使資料表被修改以新增應用程式預期不會存在的欄位,也必須繼續運作而無需修改。在 SELECT * 查詢中,* 會評估為所有資料表欄位,除了那些隱形的欄位,因此解決方案是將新欄位新增為隱形欄位。該欄位在 隱藏SELECT * 查詢之外,且應用程式會繼續像之前一樣運作。如果必要,新版本的應用程式可以通過明確參照來引用隱形欄位。

以下各節詳細說明 MySQL 如何處理隱形欄位。

DDL 陳述式與隱形欄位

欄位預設為可見。若要明確指定新欄位的可見性,請在 CREATE TABLEALTER TABLE 的欄位定義中使用 VISIBLEINVISIBLE 關鍵字。

CREATE TABLE t1 (
  i INT,
  j DATE INVISIBLE
) ENGINE = InnoDB;
ALTER TABLE t1 ADD COLUMN k INT INVISIBLE;

若要變更現有欄位的可見性,請搭配 ALTER TABLE 欄位修改子句使用 VISIBLEINVISIBLE 關鍵字。

ALTER TABLE t1 CHANGE COLUMN j j DATE VISIBLE;
ALTER TABLE t1 MODIFY COLUMN j DATE INVISIBLE;
ALTER TABLE t1 ALTER COLUMN j SET VISIBLE;

一個資料表必須至少有一個可見欄位。嘗試將所有欄位都設為隱形會產生錯誤。

隱形欄位支援一般的欄位屬性:NULLNOT NULLAUTO_INCREMENT 等等。

產生欄位可以設為隱形。

索引定義可以命名隱形欄位,包括 PRIMARY KEYUNIQUE 索引的定義。雖然資料表必須至少有一個可見欄位,但索引定義不一定要有任何可見欄位。

從資料表刪除的隱形欄位會以一般方式從任何命名該欄位的索引定義中刪除。

外鍵約束可以定義在隱形欄位上,外鍵約束也可以參照隱形欄位。

CHECK 約束可以定義在隱形欄位上。對於新或修改的列,違反隱形欄位上的 CHECK 約束會產生錯誤。

CREATE TABLE ... LIKE 包含隱形欄位,而且它們在新資料表中是隱形的。

CREATE TABLE ... SELECT 不包含隱形欄位,除非它們在 SELECT 部分被明確參照。然而,即使被明確參照,在現有資料表中為隱形的欄位在新資料表中也是可見的。

mysql> CREATE TABLE t1 (col1 INT, col2 INT INVISIBLE);
mysql> CREATE TABLE t2 AS SELECT col1, col2 FROM t1;
mysql> SHOW CREATE TABLE t2\G
*************************** 1. row ***************************
       Table: t2
Create Table: CREATE TABLE `t2` (
  `col1` int DEFAULT NULL,
  `col2` int DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci

如果應該保留隱形性,請在 CREATE TABLE ... SELECT 陳述式的 CREATE TABLE 部分中提供隱形欄位的定義。

mysql> CREATE TABLE t1 (col1 INT, col2 INT INVISIBLE);
mysql> CREATE TABLE t2 (col2 INT INVISIBLE) AS SELECT col1, col2 FROM t1;
mysql> SHOW CREATE TABLE t2\G
*************************** 1. row ***************************
       Table: t2
Create Table: CREATE TABLE `t2` (
  `col1` int DEFAULT NULL,
  `col2` int DEFAULT NULL /*!80023 INVISIBLE */
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci

視圖可以透過在定義視圖的 SELECT 陳述式中明確參照隱形欄位。在定義參照欄位的視圖後變更欄位的可見性不會變更視圖行為。

DML 陳述式與隱形欄位

對於 SELECT 陳述式,除非在選取清單中明確參照,否則隱形欄位不會是結果集的一部分。在選取清單中,*tbl_name.* 簡寫不包含隱形欄位。自然聯結不包含隱形欄位。

請考慮下列陳述式序列

mysql> CREATE TABLE t1 (col1 INT, col2 INT INVISIBLE);
mysql> INSERT INTO t1 (col1, col2) VALUES(1, 2), (3, 4);

mysql> SELECT * FROM t1;
+------+
| col1 |
+------+
|    1 |
|    3 |
+------+

mysql> SELECT col1, col2 FROM t1;
+------+------+
| col1 | col2 |
+------+------+
|    1 |    2 |
|    3 |    4 |
+------+------+

第一個 SELECT 沒有在選取清單中參照隱形欄位 col2 (因為 * 不包含隱形欄位),因此 col2 不會出現在陳述式結果中。第二個 SELECT 明確參照 col2,因此該欄位會出現在結果中。

陳述式 TABLE t1 會產生與第一個 SELECT 陳述式相同的輸出。由於無法在 TABLE 陳述式中指定欄位,因此 TABLE 永遠不會顯示隱形欄位。

對於建立新列的陳述式,除非明確參照並賦予值,否則隱形欄位會被指派其隱含預設值。有關隱含預設值的資訊,請參閱隱含預設值處理

對於 INSERT(和 REPLACE,對於未取代的列),當遺失欄位清單、欄位清單為空或不包含隱形欄位的非空欄位清單時,就會發生隱含預設值指派。

CREATE TABLE t1 (col1 INT, col2 INT INVISIBLE);
INSERT INTO t1 VALUES(...);
INSERT INTO t1 () VALUES(...);
INSERT INTO t1 (col1) VALUES(...);

對於前兩個 INSERT 陳述式,VALUES() 清單必須為每個可見欄位提供一個值,並且不為隱形欄位提供值。對於第三個 INSERT 陳述式,VALUES() 清單必須提供與命名欄位數目相同的值數目;當您使用 VALUES ROW() 而不是 VALUES() 時,也是如此。

對於 LOAD DATALOAD XML,當遺失欄位清單或不包含隱形欄位的非空欄位清單時,就會發生隱含預設值指派。輸入列不應包含隱形欄位的值。

若要為上述陳述式指派隱含預設值以外的值,請在欄位清單中明確命名隱形欄位並為其提供值。

INSERT INTO ... SELECT *REPLACE INTO ... SELECT * 不包含隱形欄位,因為 * 不包含隱形欄位。如前所述,會發生隱含預設值指派。

對於根據 PRIMARY KEYUNIQUE 索引中的值插入或忽略新列,或取代或修改現有列的陳述式,MySQL 將隱形欄位視為與可見欄位相同:隱形欄位會參與索引鍵值比較。具體來說,如果新列與現有列的唯一鍵值相同,則無論索引欄位是可見還是隱形,都會發生這些行為。

若要更新 UPDATE 陳述式的隱形欄位,請命名它們並指派值,就像處理可見欄位一樣。

隱形欄位中繼資料

有關欄位是可見還是隱形的資訊可從 Information Schema COLUMNS 資料表或 SHOW COLUMNS 輸出的 EXTRA 欄位中取得。例如

mysql> SELECT TABLE_NAME, COLUMN_NAME, EXTRA
       FROM INFORMATION_SCHEMA.COLUMNS
       WHERE TABLE_SCHEMA = 'test' AND TABLE_NAME = 't1';
+------------+-------------+-----------+
| TABLE_NAME | COLUMN_NAME | EXTRA     |
+------------+-------------+-----------+
| t1         | i           |           |
| t1         | j           |           |
| t1         | k           | INVISIBLE |
+------------+-------------+-----------+

欄位預設為可見,因此在這種情況下,EXTRA 不會顯示任何可見性資訊。對於隱形欄位,EXTRA 會顯示 INVISIBLE

SHOW CREATE TABLE 會在資料表定義中顯示隱形欄位,並且在版本特定的註解中包含 INVISIBLE 關鍵字。

mysql> SHOW CREATE TABLE t1\G
*************************** 1. row ***************************
       Table: t1
Create Table: CREATE TABLE `t1` (
  `i` int DEFAULT NULL,
  `j` int DEFAULT NULL,
  `k` int DEFAULT NULL /*!80023 INVISIBLE */
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci

mysqldump 使用 SHOW CREATE TABLE,因此它們在傾印的資料表定義中包含隱形欄位。它們也會在傾印的資料中包含隱形欄位值。

將傾印檔案重新載入到不支援隱形欄位的較舊版本 MySQL 中,會導致版本特定的註解被忽略,這會將任何隱形欄位建立為可見。

二進制日誌與隱形欄位

MySQL 在二進制日誌中的事件方面對待隱形欄位的方式如下

  • 資料表建立事件包含隱形欄位的 INVISIBLE 屬性。

  • 在列事件中,隱形欄位會被視為與可見欄位相同。如果根據 binlog_row_image 系統變數設定需要,則會包含它們。

  • 當套用列事件時,隱形欄位會被視為與列事件中的可見欄位相同。

  • 在計算寫入集時,隱形欄位會被視為與可見欄位相同。特別是,寫入集包含在隱形欄位上定義的索引。

  • mysqlbinlog 命令會在欄位中繼資料中包含可見性。