CREATE VIEW语句
CREATE [ORREPLACE ] [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
语句从视图中进行选择。)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
存在该子句,则所需的特权取决于该user
值,如“存储的对象访问控制”中所述。
引用视图后,将进行特权检查,如本节后面所述。
视图属于数据库。默认情况下,将在默认数据库中创建一个新视图。要在给定的数据库中显式创建视图,请使用db_name.view_name
语法用数据库名称限定视图名称:
CREATE VIEW test.vAS SELECT *FROM t;
SELECT
语句中的不合格表名或视图名也会相对于默认数据库进行解释。视图可以通过用适当的数据库名称限定表或视图名称来引用其他数据库中的表或视图。
在数据库中,基本表和视图共享相同的名称空间,因此基本表和视图不能具有相同的名称。
SELECT
语句检索的列可以是对表列的简单引用,也可以是使用函数,常量值,运算符等的表达式。
视图必须具有唯一的列名,且不能重复,就像基表一样。默认情况下,该SELECT
语句检索的列名称用于视图列名称。要为视图列定义显式名称,请将可选column_list
子句指定为以逗号分隔的标识符列表。中的名称数column_list
必须与该SELECT
语句检索的列数相同。
可以从多种SELECT
语句创建视图。它可以引用基表或其他视图。它可以使用joins UNION
,和子查询。该SELECT
甚至不需要引用任何表:
CREATE VIEW v_today (today)AS SELECT CURRENT_DATE ;
下面的示例定义一个视图,该视图从另一个表中选择两个列以及从这些列中计算出的表达式:
mysql>CREATE TABLE t (qty INT, price INT); mysql>INSERT INTO tVALUES (3, 50); mysql>CREATE VIEW vAS SELECT qty, price, qty*priceAS 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
子句的语句从视图中进行选择,则不确定哪个限制适用。这个道理同样适用于选项,例如ALL
,DISTINCT
或者SQL_SMALL_RESULT
后面的SELECT
关键字,并以条款,例如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
值应被指定为一个MySQL帐户,或。允许的值取决于您拥有的特权,如“存储的对象访问控制”中所述。另请参阅该部分以获取有关视图安全性的其他信息。'user_name'@'host_name'
CURRENT_USER
CURRENT_USER()
user
如果DEFINER
省略该子句,则默认定义器是执行该CREATE VIEW
语句的用户。这与DEFINER = CURRENT_USER
显式指定相同。
在视图定义中,该CURRENT_USER
函数DEFINER
默认返回视图的值。对于使用SQL SECURITY INVOKER
特征定义CURRENT_USER
的视图,返回视图调用者的帐户。有关视图中用户审核的信息,请参见“基于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 vAS SELECT *FROM tWHERE t.id = f(t.name );
假设f()
包含如下语句:
IF name IS NULLthen CALL p1();ELSE CALL p2();END IF ;
执行时,f()
需要检查其中执行语句所需的特权f()
。这可能意味着p1()
或需要特权p2()
,具体取决于中的执行路径f()
。这些特权必须在运行时检查,必须拥有特权的用户由SQL SECURITY
视图v
和函数的值确定f()
。
视图的DEFINER
and SQL SECURITY
子句是标准SQL的扩展。在标准SQL中,使用的规则处理视图SQL SECURITY DEFINER
。该标准说,视图的定义者与视图的架构所有者相同,它在视图上获得适用的特权(例如SELECT
),并可以授予它们。MySQL没有模式“所有者”的概念,因此MySQL添加了一个子句来标识定义器。该DEFINER
子句是一个扩展,其目的是拥有标准所具有的内容;即是谁定义视图的永久记录。这就是为什么默认DEFINER
值是视图创建者的帐户的原因。
可选ALGORITHM
子句是标准SQL的MySQL扩展。它影响MySQL处理视图的方式。ALGORITHM
三个值:MERGE
,TEMPTABLE
或UNDEFINED
。有关更多信息,请参见“视图处理算法”以及“通过合并或实现来优化派生表,视图引用和公用表表达式”。
有些观点是可更新的。也就是说,您可以在诸如UPDATE
,等语句中使用它们DELETE
,或INSERT
更新基础表的内容。为了使视图可更新,视图中的行与基础表中的行之间必须存在一对一的关系。还有某些其他构造会使视图不可更新。
视图中生成的列被认为是可更新的,因为可以对其进行分配。但是,如果显式更新了此类列,则唯一允许的值为DEFAULT
。有关生成的列的信息,请参见“创建表和生成的列”。
WITH CHECK OPTION
可以为可更新视图提供该子句,以防止对行中的WHERE
子句除外的行进行插入或更新select_statement
。
在WITH CHECK OPTION
可更新视图的子句中,当根据另一个视图定义该视图时,LOCAL
and CASCADED
关键字确定检查测试的范围。LOCAL
关键字CHECK OPTION
仅将关键字限制为已定义的视图。CASCADED
使对基础视图的检查也被评估。如果未指定任何关键字,则默认值为CASCADED
。
有关可更新视图和该WITH CHECK OPTION
子句的更多信息,请参见“更新和插入视图”和“带有检查选项子句的视图”。