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 VIEW 等同于 CREATE VIEW。如果视图确实存在,则 CREATE OR REPLACE VIEW 替换它。select_statement 是一个提供视图定义的 SELECT 语句。select_statement 可以从基础表、其他视图中进行查询。从MySQL 8.0.19开始,SELECT 语句可以使用 VALUES 语句作为源,也可以用 TABLE 语句代替,比如 CREATE TABLE ... SELECT。视图的定义在创建时被“冻结”,不受后续对基础表定义更改的影响。例如,如果一个视图被定义为表上的 SELECT *,随后添加到表中的新列不会成为视图的一部分,而从表中删除列,在从视图中进行选择时将导致错误。ALGORITHM 子句影响 MySQL 处理视图的方式。DEFINER 和 SQL SECURITY 子句指定在视图调用时检查访问权限时使用的安全上下文。WITH CHECK OPTION 子句可用于约束对视图引用的表中的行进行的插入或更新。这些子句将在本节的后面进行介绍。CREATE VIEW 语句需要视图的 CREATE VIEW 权限,以及 SELECT 语句所选择列的某些权限。对于 SELECT 语句中其他地方使用的列,必须具有 SELECT 权限。如果存在 OR REPLACE 子句,则还必须具有视图的 DROP 权限。如果存在 DEFINER 子句,则所需的权限取决于用户。视图属于数据库。默认情况下,新建视图属于默认数据库。要在给定的数据库中显式创建视图,请使用 db_name.view_name 语法用数据库名限定视图名:CREATE VIEW test.v AS SELECT * FROM t;
复制
SELECT 语句中的非限定表或视图名称也会根据默认数据库进行解释。通过使用适当的数据库名称限定,视图可以引用其他数据库中的表或视图。在数据库中,基础表和视图共享相同的命名空间,因此基础表和视图不能有相同的名称。SELECT 语句检索的列可以是对表列的简单引用,也可以是使用函数、常量值、操作符等的表达式。视图必须有唯一的列名,就像基础表一样。默认情况下,SELECT 语句检索到的列的名称用于视图列名。要显式定义视图列的名称,请将可选的 column_list 子句指定为用逗号分隔的标识符列表。column_list 中的名称数必须与 SELECT 语句检索的列数相同。可以通过多种 SELECT 语句创建视图。它可以引用基础表或其他视图。它可以使用联接、联合和子查询。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 语句不能引用程序参数或局部变量。● 定义中引用的任何表或视图都必须存在。如果在创建视图之后,定义引用的表或视图被删除,那么使用视图会导致错误。若要检查视图定义是否存在此类问题,请使用 CHECK TABLE 语句。● 定义不能引用 TEMPORARY 表,也不能创建 TEMPORARY 视图。● SELECT 语句中列名的别名最大长度64个字符(而不是256个字符的最大别名长度)。在视图定义中允许使用 ORDER BY,但是如果使用 ORDER BY 语句从视图中进行选择,则会忽略视图自己的 ORDER BY。对于定义中的其他选项或子句,它们被添加到引用视图的语句的选项或子句中,但效果是不确定的。例如,如果视图定义包含 LIMIT 子句,使用 LIMIT 子句从视图中进行查询,则应用哪个限制是不确定的。同样的原则也适用于 SELECT 关键字后面的 ALL、DISTINCT 或 SQL_SMALL_RESULT 等选项,以及 INTO、FOR UPDATE、FOR SHARE、LOCK IN SHARE MODE 和 PROCEDURE 等子句。如果通过改变系统变量来改变查询处理环境,则可能会影响从视图获得的结果: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)
复制
当执行引用视图的语句时,DEFINER 和 SQL SECURITY 子句确定在检查视图的访问权限时使用哪个 MySQL 帐户。有效的 SQL SECURITY 典型值是 DEFINER(缺省值)和 INVOKER。表示定义或调用视图的用户必须分别拥有所需的权限。如果存在 DEFINER 子句,则用户值应该是指定为 'user_name'@'host_name'、CURRENT_USER 或 CURRENT_USER() 的MySQL帐户。允许的用户值取决于您拥有的权限。如果省略了 DEFINER 子句,则默认的定义者是执行 CREATE VIEW 语句的用户。这与显式指定 DEFINER = CURRENT_USER 相同。在视图定义中,CURRENT_USER 函数默认返回视图的 DEFINER 值。对于使用 SQL SECURITY INVOKER 定义的视图,CURRENT_USER 返回视图调用者的帐户。在使用 SQL SECURITY DEFINER 定义的存储例程中,CURRENT_USER 返回例程的 DEFINER 值。如果视图定义中 DEFINER 值为 CURRENT_USER,那么这也会影响在这个例程中定义的视图。● 在视图定义时,视图创建者必须具有使用视图访问的顶级对象所需的权限。例如,如果视图定义引用表列,创建者必须对定义的选择列表中的每一列具有某种权限,对定义中其他地方使用的列具有 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);
复制
IF name IS NULL then
CALL p1();
ELSE
CALL p2();
END IF;
复制
当 f() 执行时,需要检查在 f() 中执行语句所需的权限。这可能意味着执行 p1() 或 p2() 需要权限,具体取决于 f() 中的执行路径。必须在运行时检查这些权限,视图 v 和函数 f() 的 SQL SECURITY 值决定了哪个用户必须拥有这些权限。用于视图的 DEFINER 和 SQL SECURITY 子句是对标准SQL的扩展。在标准SQL中,视图是使用 SQL SECURITY DEFINER 规则处理的。标准规定,视图的定义者(与视图模式的所有者相同)在视图上获得适当的权限(例如,SELECT),并可以授予这些权限。MySQL 没有模式“owner”的概念,所以添加了一个子句来标识定义者。DEFINER 子句是一种扩展,也就是记录谁定义了视图。这就是为什么默认的 DEFINER 值是视图创建者的帐户。可选 ALGORITHM 子句是 MySQL 对标准 SQL 的扩展。它影响 MySQL 处理视图的方式。ALGORITHM 接受三个值: MERGE、TEMPTABLE 或 UNDEFINED。有些视图是可更新的。也就是说,可以在 UPDATE、DELETE 或 INSERT 等语句中使用它们来更新基础表的内容。要使视图可更新,视图中的行与基础表中的行之间必须存在一对一的对应关系。还有一些其他结构使视图不可更新。视图中生成列被认为是可更新的,因为可以对其赋值。但是,如果这样的列被显式更新,唯一允许的值是 DEFAULT。可以对可更新视图使用 WITH CHECK OPTION 子句,以防止对行进行插入或更新,但 select_statement 中的 WHERE 子句为真的情况除外。在可更新视图的 WITH CHECK OPTION 子句中,当根据另一个视图定义视图时,LOCAL 和 CASCADED 关键字确定检查测试的范围。LOCAL 关键字仅将 CHECK OPTION 限制为定义的视图。使用 CASCADED 关键字也将同时对基础视图进行检查。当两个关键字都没有给出时,默认是 CASCADED。https://dev.mysql.com/doc/refman/8.0/en/create-view.html