Documentation Home
MySQL 8.3 Reference Manual
Related Documentation Download this Manual
PDF (US Ltr) - 40.8Mb
PDF (A4) - 40.9Mb
Man Pages (TGZ) - 294.0Kb
Man Pages (Zip) - 409.0Kb
Info (Gzip) - 4.0Mb
Info (Zip) - 4.0Mb
Excerpts from this Manual

15.1.20.10 不可见列

MySQL 8.3 支持不可见列。不可见列通常对查询隐藏,但可以通过明确引用来访问。

例如,假设应用程序使用 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;

要更改现有列的可见性,请使用 VISIBLEINVISIBLE 关键字与 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;

表必须至少有一个可见列。尝试使所有列不可见将产生错误。

不可见列支持通常的列属性: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 部分的 CREATE TABLE ... SELECT 语句中提供不可见列的定义:

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 语句,请命名它们并分配值,就像可见的列一样。

不可见列元数据

关于列是否可见或不可见的信息可以从信息模式 EXTRA 列的 COLUMNS 表或 SHOW COLUMNS 输出中获得。例如:

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

mysqldumpmysqlpump 使用 SHOW CREATE TABLE,因此它们在转储表定义中包括不可见列。它们还包括不可见列值在转储数据中。

将转储文件重新加载到不支持不可见列的旧版本 MySQL 中时,版本特定的注释将被忽略,从而创建不可见列作为可见列。

二进制日志和不可见列

MySQL 将不可见列视为二进制日志中的以下事件:

  • 表创建事件包括不可见列的 INVISIBLE 属性。

  • 不可见列在行事件中被视为可见列。它们根据 binlog_row_image 系统变量设置需要时包括。

  • 当行事件被应用时,不可见列被视为可见列。

  • 不可见列在计算写集时被视为可见列。特别是,写集包括在不可见列上定义的索引。

  • mysqlbinlog 命令包括列元数据中的可见性信息。