MySQL 8.4 支援隱形欄位。隱形欄位通常對查詢隱藏,但如果明確引用,則可以存取。
舉例說明隱形欄位可能派上用場的情況:假設某應用程式使用 SELECT *
查詢來存取資料表,而且即使修改資料表以新增應用程式預期不會出現的新欄位,也必須繼續運作而無需修改。在 SELECT *
查詢中,*
會評估為所有資料表欄位,除了那些隱形的欄位,因此解決方案是將新欄位新增為隱形欄位。該欄位對 SELECT *
查詢保持「「隱藏」」,應用程式繼續像以前一樣運作。如果需要,應用程式的較新版本可以明確參考隱形欄位。
以下章節詳細說明 MySQL 如何處理隱形欄位。
預設情況下,欄位是可見的。若要明確指定新欄位的可見性,請在 CREATE TABLE
或 ALTER TABLE
的欄位定義中使用 VISIBLE
或 INVISIBLE
關鍵字。
CREATE TABLE t1 (
i INT,
j DATE INVISIBLE
) ENGINE = InnoDB;
ALTER TABLE t1 ADD COLUMN k INT INVISIBLE;
若要變更現有欄位的可見性,請將 VISIBLE
或 INVISIBLE
關鍵字與其中一個 ALTER TABLE
欄位修改子句搭配使用。
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;
資料表必須至少有一個可見欄位。嘗試讓所有欄位都隱形會產生錯誤。
隱形欄位支援常用的欄位屬性:NULL
、NOT NULL
、AUTO_INCREMENT
等等。
產生的欄位可以是隱形的。
索引定義可以命名隱形欄位,包括 PRIMARY KEY
和 UNIQUE
索引的定義。雖然資料表必須至少有一個可見欄位,但索引定義不必有任何可見欄位。
從資料表卸除的隱形欄位會以通常的方式從命名該欄位的任何索引定義中卸除。
外鍵約束可以在隱形欄位上定義,而且外鍵約束可以參考隱形欄位。
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
語句中明確參考來參考隱形欄位。在定義參考欄位的檢視之後,變更欄位的可見性不會變更檢視的行為。
對於 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 DATA
和 LOAD XML
,在遺失欄位清單或不包含隱形欄位的非空欄位清單的情況下,會發生隱含的預設指派。輸入資料列不應包含隱形欄位的值。
若要為上述語句指派隱含預設值以外的值,請在欄位清單中明確命名隱形欄位並為其提供值。
INSERT INTO ... SELECT *
和 REPLACE INTO ... SELECT *
不包含隱形欄位,因為 *
不包含隱形欄位。如先前所述,會發生隱含的預設指派。
對於根據 PRIMARY KEY
或 UNIQUE
索引中的值插入或忽略新資料列,或取代或修改現有資料列的語句,MySQL 會將隱形欄位視為與可見欄位相同:隱形欄位會參與鍵值比較。具體而言,如果新資料列的唯一索引鍵值與現有資料列的值相同,則無論索引欄位是可見或隱形,都會發生這些行為。
若要更新 UPDATE
語句的隱形欄位,請命名它們並指派一個值,就像處理可見欄位一樣。
關於欄位是否可見或隱形的資訊可從資訊綱要 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 命令會在欄位元數據中包含可見性資訊。