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

MySQL 8.3 Reference Manual  /  ...  /  CREATE VIEW Statement

15.1.23 创建视图语句

CREATE
    [OR REPLACE]
    [ALGORITHM = {UNDEFINED | MERGE | TEMPTABLE}]
    [DEFINER = user]
    [SQL SECURITY { DEFINER | INVOKER }]
    VIEW view_name [(column_list)]
    AS select_statement
    [WITH [CASCADED | LOCAL] CHECK OPTION]

CREATE VIEW 语句创建一个新的视图,或者如果给出了 OR REPLACE 子句,则替换现有的视图。如果视图不存在, CREATE OR REPLACE VIEWCREATE VIEW 相同。如果视图已经存在, CREATE OR REPLACE VIEW 将其替换。

有关视图使用限制的信息,请参阅 第 27.9 节,“视图限制”

select_statement 是一个 SELECT 语句,提供了视图的定义。(从视图中选择实际上是使用 SELECT 语句。)该 select_statement 可以从基本表或其他视图中选择。该 SELECT 语句可以使用 VALUES 语句作为其源,或者可以被 TABLE 语句所取代,如同 CREATE TABLE ... SELECT

视图定义是在创建时“冻结”的,不受后续对基础表定义的更改的影响。例如,如果视图被定义为在表上选择所有列,后来添加到表中的新列不会成为视图的一部分,而从表中删除的列将在从视图中选择时导致错误。

ALGORITHM 子句影响 MySQL 如何处理视图。DEFINERSQL SECURITY 子句指定了在视图调用时检查访问权限的安全上下文。WITH CHECK OPTION 子句可以用于约束对视图引用的表中的行的插入或更新。这些子句将在本节后面描述。

CREATE VIEW 语句需要对视图具有 CREATE VIEW 权限,并且对每个选择的列具有某些权限的 SELECT 语句。对于在 SELECT 语句中使用的其他列,您必须具有 SELECT 权限。如果存在 OR REPLACE 子句,您还必须具有视图的 DROP 权限。如果存在 DEFINER 子句,所需的权限取决于 user 值,如 第 27.6 节,“存储对象访问控制” 中所讨论的那样。

当视图被引用时,将按照本节后面所述的方式进行权限检查。

视图属于某个数据库。默认情况下,新视图将创建在默认数据库中。要在给定的数据库中显式创建视图,请使用 db_name.view_name 语法来限定视图名称与数据库名称:

CREATE VIEW test.v AS SELECT * FROM t;

SELECT 语句中的未限定表或视图名称也将相对于默认数据库进行解释。视图可以通过限定表或视图名称以数据库名称来引用其他数据库中的表或视图。

在数据库中,基本表和视图共享相同的命名空间,因此基本表和视图不能具有相同的名称。

SELECT 语句检索的列可以是简单的表列引用,也可以是使用函数、常量值、运算符等的表达式。

视图必须具有唯一的列名称,且不允许重复,就像基本表一样。默认情况下,SELECT 语句检索的列名称将用于视图列名称。要为视图列定义明确的名称,请指定可选的 column_list 子句作为逗号分隔的标识符列表。column_list 中的名称数量必须与 SELECT 语句检索的列数量相同。

视图可以从多种类型的 SELECT 语句创建。它可以引用基本表或其他视图。它可以使用连接、UNION 和子查询。该 SELECT 语句不需要引用任何表:

CREATE VIEW v_today (today) AS SELECT CURRENT_DATE;

以下示例定义了一个视图,该视图从另一个表中选择两列,并计算出这些列的表达式:

mysql> CREATE TABLE t (qty INT, price INT);
mysql> INSERT INTO t VALUES(3, 50);
mysql> CREATE VIEW v AS SELECT qty, price, qty*price AS value FROM t;
mysql> SELECT * FROM v;
+------+-------+-------+
| qty  | price | value |
+------+-------+-------+
|    3 |    50 |   150 |
+------+-------+-------+

视图定义受以下限制:

  • SELECT 语句不能引用系统变量或用户定义变量。

  • 在存储程序中,该 SELECT 语句不能引用程序参数或局部变量。

  • SELECT 语句不能引用准备语句参数。

  • 在定义中引用的任何表或视图必须存在。如果在创建视图后,定义中引用的表或视图被删除,使用视图将导致错误。要检查视图定义中的这种问题,请使用 CHECK TABLE 语句。

  • 定义不能引用 TEMPORARY 表,您也不能创建 TEMPORARY 视图。

  • 您不能将触发器与视图关联。

  • 别名列名在 SELECT 语句中的检查是针对最大列长度的 64 个字符(而不是别名长度的 256 个字符)。

ORDER BY 在视图定义中是允许的,但如果您使用带有自己的 ORDER BY 的语句从视图中选择,它将被忽略。

对于定义中的其他选项或子句,它们将被添加到引用视图的语句的选项或子句中,但效果未定义。例如,如果视图定义包括 LIMIT 子句,并且您使用带有自己的 LIMIT 子句的语句从视图中选择,那么哪个限制适用将是未定义的。同样的原则也适用于 ALLDISTINCTSQL_SMALL_RESULT 等选项,它们跟随 SELECT 关键字,以及 INTOFOR UPDATEFOR SHARELOCK IN SHARE MODEPROCEDURE 等子句。

从视图中获得的结果可能会受到影响,如果您通过更改系统变量来更改查询处理环境:

mysql> CREATE VIEW v (mycol) AS SELECT 'abc';
Query OK, 0 rows affected (0.01 sec)

mysql> SET sql_mode = '';
Query OK, 0 rows affected (0.00 sec)

mysql> SELECT "mycol" FROM v;
+-------+
| mycol |
+-------+
| mycol |
+-------+
1 row in set (0.01 sec)

mysql> SET sql_mode = 'ANSI_QUOTES';
Query OK, 0 rows affected (0.00 sec)

mysql> SELECT "mycol" FROM v;
+-------+
| mycol |
+-------+
| abc   |
+-------+
1 row in set (0.00 sec)

视图的 DEFINERSQL SECURITY 子句确定了在执行引用视图的语句时用于检查访问权限的 MySQL 帐户。有效的 SQL SECURITY 特征值是 DEFINER(默认)和 INVOKER。这些指示需要的权限必须由定义或调用视图的用户持有。

如果存在 DEFINER 子句,user 值应该是一个指定为 'user_name'@'host_name' 的 MySQL 帐户,CURRENT_USERCURRENT_USER()。允许的 user 值取决于您持有的权限,如 第 27.6 节,“存储对象访问控制” 中所讨论的那样。还可以查看该节以获取关于视图安全的更多信息。

如果省略 DEFINER 子句,默认定义者是执行 CREATE VIEW 语句的用户。这与指定 DEFINER = CURRENT_USER 是相同的。

在视图定义中,CURRENT_USER 函数默认返回视图的 DEFINER 值。对于定义为 SQL SECURITY INVOKER 特征的视图,CURRENT_USER 返回视图的调用者帐户。关于视图中的用户审核,请参阅 第 8.2.23 节,“基于 SQL 的帐户活动审核”

在定义为 SQL SECURITY DEFINER 特征的存储过程中,CURRENT_USER 返回过程的 DEFINER 值。这也影响了在该过程中定义的视图,如果视图定义包含 DEFINER 值为 CURRENT_USER

MySQL 按照以下方式检查视图权限:

  • 在视图定义时,视图创建者必须拥有访问顶级对象的权限,例如,如果视图定义引用表列,创建者必须拥有选择列表中每列的某些权限,以及定义中使用的每列的 SELECT 权限。如果定义引用存储函数,只能检查函数调用的权限。在函数执行时可以检查执行路径中的权限:对于不同的调用,函数中的不同执行路径可能会被采取。

  • 引用视图的用户必须拥有适当的权限来访问它(从中选择 SELECT 权限,插入 INSERT 权限等)。

  • 当视图被引用时,对视图访问的对象的权限将根据视图的 DEFINER 帐户或调用者来检查,具体取决于 SQL SECURITY 特征是 DEFINER 还是 INVOKER

  • 如果对视图的引用导致存储函数的执行,那么在函数中执行的语句的权限检查将取决于函数的 SQL SECURITY 特征是 DEFINER 还是 INVOKER。如果安全特征是 DEFINER,函数将以 DEFINER 帐户的权限运行。如果特征是 INVOKER,函数将以视图的 SQL SECURITY 特征确定的权限运行。

示例:视图可能依赖于存储函数,而该函数可能会调用其他存储例程。例如,以下视图调用存储函数 f()

CREATE VIEW v AS SELECT * FROM t WHERE t.id = f(t.name);

假设 f() 包含以下语句:

IF name IS NULL then
  CALL p1();
ELSE
  CALL p2();
END IF;

f() 执行时,需要检查执行语句中的权限。这可能意味着需要 p1()p2() 的权限,具体取决于 f() 中的执行路径。这些权限必须在运行时检查,而拥有这些权限的用户将根据视图 v 和函数 f()SQL SECURITY 值来确定。

视图的 DEFINERSQL SECURITY 子句是标准 SQL 的扩展。在标准 SQL 中,视图是使用 SQL SECURITY DEFINER 规则处理的。标准规定,视图的定义者(即视图 schema 的所有者)获得了视图的适用权限(例如,SELECT),并且可以授予它们。MySQL 没有 schema “所有者”的概念,因此 MySQL 添加了一个子句来标识定义者。DEFINER 子句是一个扩展,旨在拥有标准所具有的内容,即永久记录谁定义了视图。这就是为什么默认 DEFINER 值是视图创建者的账户。

可选的 ALGORITHM 子句是 MySQL 对标准 SQL 的扩展。它影响 MySQL 如何处理视图。ALGORITHM 取三个值:MERGETEMPTABLEUNDEFINED。有关更多信息,请参阅 第 27.5.2 节,“视图处理算法”,以及 第 10.2.2.4 节,“使用合并或物化优化派生表、视图引用和公共表表达式”

一些视图是可更新的。这意味着,您可以在语句中使用它们,例如 UPDATEDELETEINSERT,以更新基础表的内容。要使视图可更新,必须在视图和基础表之间存在一对一的关系。此外,还有一些其他结构使视图不可更新。

视图中的生成列被认为是可更新的,因为可以分配给它。然而,如果显式更新了该列,则唯一允许的值是 DEFAULT。有关生成列的信息,请参阅 第 15.1.20.8 节,“CREATE TABLE 和生成列”

可以为可更新视图提供 WITH CHECK OPTION 子句,以防止插入或更新除 select_statement 中的 WHERE 子句为 true 的行以外的所有行。

在可更新视图的 WITH CHECK OPTION 子句中,LOCALCASCADED 关键字确定了视图定义时的检查测试范围。当视图定义为另一个视图时,这些关键字生效。LOCAL 关键字将 CHECK OPTION 仅限制在当前定义的视图上。CASCADED 导致对基础视图的检查也被评估。当没有给定关键字时,默认为 CASCADED

有关可更新视图和 WITH CHECK OPTION 子句的更多信息,请参阅 第 27.5.3 节,“可更新和可插入视图”第 27.5.4 节,“视图 WITH CHECK OPTION 子句”