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 VIEW
等同于 CREATE VIEW
。如果视图存在,CREATE OR REPLACE VIEW
将其替换。
关于视图使用的限制信息,请参见第27.9节,“视图限制”。
该select_statement
是一个SELECT
语句,提供视图的定义。 (从视图中选择实际上是使用SELECT
语句。) select_statement
可以从基本表或其他视图中选择数据。该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
子句,所需权限取决于 user
值,如第27.6节,“存储对象访问控制” 中所讨论的。
当视图被引用时,权限检查将按照后面这个部分描述进行。
视图属于一个数据库。默认情况下,新创建的视图将在默认数据库中创建。要在指定数据库中显式创建视图,请使用 db_name.view_name
语法来限定视图名称:
CREATE VIEW test.v AS SELECT * FROM t;
未qualified 的表或视图名称在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
语句。 -
定义不能引用临时表,您也不能创建临时视图。
-
您不能与视图关联触发器。
-
SELECT 语句中的列别名在对比时,检查的是64个字符的最大列长度,而不是256个字符的最大别名长度。
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)
定義者和安全性子句确定在执行语句时,檢查视图访问权限的MySQL賬戶。有效的安全性特征值是DEFINER
(默认)和INVOKER
。這些指示所需權限必須由定義或調用視圖的用戶擁有,分別。
如果存在DEFINER
子句,則應該是指定的MySQL賬戶,例如'user_name
'@'host_name
'、CURRENT_USER
或CURRENT_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
值。同样,如果视图定义包含CURRENT_USER
的 DEFINER
值,那么也影响在该程序中定义的视图。
MySQL 对视图权限进行检查:
-
在视图定义时,视图创建者必须拥有访问视图中顶级对象所需的权限。例如,如果视图定义引用表列,创建者必须对每个列在选择列表中有某些权限,并且对定义中的其他列使用
SELECT
权限。如果定义引用存储函数,只需要检查调用该函数所需的权限。由于函数执行路径可能不同,不能在函数调用时检查所有权限。 -
引用视图的用户必须拥有访问它的适当权限(对其进行选择、插入等).
-
当视图被引用后,对视图访问对象的权限将根据视图的
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
值确定。
视图的DEFINER
和SQL SECURITY
子句是标准SQL的扩展。在标准SQL中,视图使用SQL SECURITY DEFINER
规则。标准说的是视图定义者(与视图架构所有者相同)获得适用的权限(例如SELECT
),并且可以授予它们。MySQL没有架构“owner”概念,所以MySQL添加了一个子句来标识定义者。DEFINER
子句是扩展,意在记录谁定义了视图。这就是为什么默认的DEFINER
值是视图创建者的账户。
可选的ALGORITHM
子句是MySQL对标准SQL的扩展。它影响MySQL处理视图。ALGORITHM
有三个值:MERGE
、TEMPTABLE
或UNDEFINED
。更多信息,请参见第27.5.2节,“视图处理算法”,以及第10.2.2.4节,“优化派生表、视图引用和公共表达式使用合并或物化”。
有些视图是可更新的。即,您可以使用UPDATE
、DELETE
或INSERT
语句来更新 underlying 表的内容。为使视图可更新,必须存在视图和 underlying 表之间的一对一关系。此外,还有一些构造使视图不可更新。
在视图中生成的列被认为是可更新的,因为可以将其分配给它。但是,如果这种列被显式更新,唯一允许的值是DEFAULT
。关于生成列,请参见第15.1.20.8节,“CREATE TABLE 和生成列”。
在可更新视图中,可以给出WITH CHECK OPTION
子句,以防止除select_statement
中的WHERE
子句为真的插入或更新行。
关于可更新视图和WITH CHECK OPTION
子句的更多信息,请参见第27.5.3节,“可更新和可插入视图”,和第27.5.4节,“WITH CHECK OPTION子句”。