04MySQL的视图、存储过程和触发器

一、MySQL的视图

视图(view)是一个虚拟表,非真实存在,其本质是根据SQL语句获取动态的数据集,并为其命名,用户使用时只需使用视图名称即可获取结果集,并可以将其当作表来使用。数据库中只存放了视图的定义,而并没有存放视图中的数据。这些数据存放在原来的表中。使用视图查询数据时,数据库系统会从原来的表中取出对应的数据。因此,视图中的数据是依赖于原来的表中的数据的。一旦表中的数据发生改变,显示在视图中的数据也会发生改变。

视图的作用有

  • 简化代码,可以把重复使用的查询封装成视图重复使用,同时可以使复杂的查询易于理解和使用。
  • 安全原因,如果一张表中有很多数据,很多信息不希望让所有人看到,此时可以使用视图

1.1 视图的创建

创建视图的语法为

create [or replace] [algorithm = {undefined | merge | temptable}]
view view_name [(column_list)]
as select_statement
[with [cascaded | local] check option]

/*
参数说明:
(1)algorithm:可选项,表示视图选择的算法。
(2)view_name :表示要创建的视图名称。
(3)column_list:可选项,指定视图中各个属性的名词,默认情况下与SELECT语句中的查询的属性相同。
(4)select_statement:表示一个完整的查询语句,将查询记录导入视图中。
(5)[with [cascaded | local] check option]:可选项,表示更新视图时要保证在该视图的权限范围之内。
*/

1.2 修改视图

修改视图是指修改数据库中已存在的表的定义。当基本表的某些字段发生改变时,可以通过修改视图来保持视图和基本表之间一致。MySQL中通过CREATE OR REPLACE VIEW语句和ALTER VIEW语句来修改视图。

alter view 视图名 as select语句

1.3 更新视图

某些视图是可更新的。也就是说,可以在UPDATE、DELETE或INSERT等语句中使用它们,以更新基表的内容。对于可更新的视图,在视图中的行和基表中的行之间必须具有一对一的关系。如果视图包含下述结构中的任何一种,那么它就是不可更新的:

  • 聚合函数(SUM(), MIN(), MAX(), COUNT()等)
  • DISTINCT
  • GROUP BY
  • HAVING
  • UNION或UNION ALL
  • 位于选择列表中的子查询
  • JOIN
  • FROM子句中的不可更新视图
  • WHERE子句中的子查询,引用FROM子句中的表。
  • 仅引用文字值(在该情况下,没有要更新的基本表)

视图中虽然可以更新数据,但是有很多的限制。一般情况下,最好将视图作为查询数据的虚拟表,而不要通过视图更新数据。因为,使用视图更新数据时,如果没有全面考虑在视图中更新数据的限制,就可能会造成数据更新失败。

1.4 其他操作

  • 重命名视图
-- rename table 视图名 to 新视图名; 
rename table view1_emp to my_view1
  • 删除视图
-- drop view 视图名[,视图名…];
drop view if exists view_student;

删除视图时,只能删除视图的定义,不会删除数据。

二、MySQL的存储过程

简单的说,存储过程就是一组SQL语句集,功能强大,可以实现一些比较复杂的逻辑功能,类似于JAVA语言中的方法;存储过就是数据库 SQL 语言层面的代码封装与重用。

存储过程的特性:

  • 有输入输出参数,可以声明变量,有if/else, case,while等控制语句,通过编写存储过程,可以实现复杂的逻辑功能;
  • 函数的普遍特性:模块化,封装,代码复用;
  • 速度快,只有首次执行需经过编译和优化步骤,后续被调用可以直接执行,省去以上步骤;

2.1 存储过程的使用

其格式为

delimiter 自定义结束符号
create procedure 储存名([ in ,out ,inout ] 参数名 数据类形...)
begin
  sql语句
end 自定义的结束符合
delimiter ;

-- 调用存储过程
call 储存名(); 

2.2 变量定义

2.2.1 局部变量

用户自定义,在begin/end块中有效

-- 声明变量 
-- declare var_name type [default var_value]; 
declare nickname varchar(32);
-- 变量赋值
set nickname = ‘zhangsan’;  

MySQL 中还可以使用 SELECT..INTO 语句为变量赋值。其基本语法如下:

select col_name [...] into var_name[,...] 
from table_name wehre condition 
/*
其中:
col_name 参数表示查询的字段名称;
var_name 参数是变量的名称;
table_name 参数指表的名称;
condition 参数指查询条件。
注意:当将查询结果赋值给变量时,该查询语句的返回结果只能是单行单列。
*/

2.2.2 用户变量

用户自定义,当前会话(连接)有效。类比java的成员变量 不需要提前声明,使用即声明

-- 语法: 
@var_name

例如

delimiter $$
create procedure proc04()
begin
    set @var_name01  = 'ZS';
end $$
delimiter;
call proc04() ;

2.2.3 系统变量

系统变量又分为全局变量与会话变量

  • 全局变量在MYSQL启动的时候由服务器自动将它们初始化为默认值,这些默认值可以通过更改my.ini这个文件来更改。
  • 会话变量在每次建立一个新的连接的时候,由MYSQL来初始化。MYSQL会将当前所有全局变量的值复制一份。来做为会话变量。

也就是说,如果在建立会话以后,没有手动更改过会话变量与全局变量的值,那所有这些变量的值都是一样的。全局变量与会话变量的区别就在于,对全局变量的修改会影响到整个服务器,但是对会话变量的修改,只会影响到当前的会话(也就是当前的数据库连接)。有些系统变量的值是可以利用语句来动态进行更改的,但是有些系统变量的值却是只读的,对于那些可以更改的系统变量,我们可以利用set语句进行更改。

全局变量的语法:

@@global.var_name
-- 查看全局变量 
show global variables; 
-- 查看某全局变量 
select @@global.auto_increment_increment; 
-- 修改全局变量的值 
set global sort_buffer_size = 40000; 
set @@global.sort_buffer_size = 40000;

会话变量的语法

@@session.var_name
-- 查看会话变量
show session variables;
-- 查看某会话变量 
select @@session.auto_increment_increment;
-- 修改会话变量的值
set session sort_buffer_size = 50000; 
set @@session.sort_buffer_size = 50000 ;

2.3 存储过程传参

  • in 表示传入的参数, 可以传入数值或者变量,即使传入变量,并不会更改变量的值,可以内部更改,仅仅作用在函数范围内。

  • out 表示从存储过程内部传值给调用者

  • inout 表示从外部传入的参数经过修改后可以返回的变量,既可以使用传入变量的值也可以修改变量的值(即使函数执行完)

2.4 流程控制

2.4.1 判断

IF语句包含多个条件判断,根据结果为TRUE、FALSE执行语句,与编程语言中的if、else if、else语法类似,其语法格式如下

-- 语法
if search_condition_1 then statement_list_1
    [elseif search_condition_2 then statement_list_2] ...
    [else statement_list_n]
end if

CASE是另一个条件判断的语句,类似于编程语言中的switch语法

-- 语法一(类比java的switch):
case case_value
    when when_value then statement_list
    [when when_value then statement_list] ...
    [else statement_list]
end case
-- 语法二:
case
    when search_condition then statement_list
    [when search_condition then statement_list] ...
    [else statement_list]
end case

2.4.2 循环

循环是一段在程序中只出现一次,但可能会连续运行多次的代码,循环中的代码会运行特定的次数,或者是运行到特定条件成立时结束循环

循环的类别包括

  • while
  • repeat
  • loop
-- 类似于while
[标签:] while 循环条件 do
    循环体;
end while[标签];

循环控制包括

  • leave 类似于 break,跳出,结束当前所在的循环
  • iterate类似于 continue,继续,结束本次循环,继续下一次
-- 类似于do while
[标签:] repeat 
 循环体;
until 条件表达式
end repeat [标签];
[标签:] loop
  循环体;
  if 条件表达式 then 
     leave [标签]; 
  end if;
end loop;

2.5 游标

游标(cursor)是用来存储查询结果集的数据类型 , 在存储过程和函数中可以使用光标对结果集进行循环的处理。光标的使用包括光标的声明、OPEN、FETCH 和 CLOSE.

-- 声明语法
declare cursor_name cursor for select_statement
-- 打开语法
open cursor_name
-- 取值语法
fetch cursor_name into var_name [, var_name] ...
-- 关闭语法
close cursor_name

2.6 异常处理

MySql存储过程也提供了对异常处理的功能:通过定义HANDLER来完成异常声明的实现.

官方文档:https://dev.mysql.com/doc/refman/5.7/en/declare-handler.html

DECLARE handler_action HANDLER
    FOR condition_value [, condition_value] ...
    statement

/*
handler_action: {
    CONTINUE    -- 继续执行
  | EXIT        -- 退出程序
  | UNDO        -- 不支持,暂时不使用
}
 
condition_value: {
    mysql_error_code        -- MySQL的条件码
  | condition_name          -- MySQL的条件名
  | SQLWARNING              
  | NOT FOUND               
  | SQLEXCEPTION    
*/

在语法中,变量声明、游标声明、handler声明是必须按照先后顺序书写的,否则创建存储过程出错。

三、MySQL的存储函数

MySQL存储函数(自定义函数),函数一般用于计算和返回一个值,可以将经常需要使用的计算或功能写成一个函数。存储函数和存储过程一样,都是在数据库中定义一些 SQL 语句的集合。

存储函数与存储过程的区别在于

  • 存储函数有且只有一个返回值,而存储过程可以有多个返回值,也可以没有返回值。

  • 存储函数只能有输入参数,而且不能带in, 而存储过程可以有多个in,out,inout参数。

  • 存储过程中的语句功能更强大,存储过程可以实现很复杂的业务逻辑,而函数有很多限制,如不能在函数中使用insert,update,delete,create等语句;

  • 存储函数只完成查询的工作,可接受输入参数并返回一个结果,也就是函数实现的功能针对性比较强。

  • 存储过程可以调用存储函数。但函数不能调用存储过程。

  • 存储过程一般是作为一个独立的部分来执行(call调用)。而函数可以作为查询语句的一个部分来调用.

在MySQL中,创建存储函数使用create function关键字,其基本形式如下:

create function func_name ([param_name type[,...]])
returns type
[characteristic ...] 
begin
    routine_body
end;

/*
func_name :存储函数的名称。
param_name type:可选项,指定存储函数的参数。type参数用于指定存储函数的参数类型,该类型可以是MySQL数据库中所有支持的类型。
RETURNS type:指定返回值的类型。
characteristic:可选项,指定存储函数的特性。
routine_body:SQL代码内容。
*/

四、MySQL的触发器

触发器,就是一种特殊的存储过程。触发器和存储过程一样是一个能够完成特定功能、存储在数据库服务器上的SQL片段,但是触发器无需调用,当对数据库表中的数据执行DML操作时自动触发这个SQL片段的执行,无需手动条用。在MySQL中,只有执行insert,delete,update操作时才能触发触发器的执行,触发器的这种特性可以协助应用在数据库端确保数据的完整性 , 日志记录 , 数据校验等操作 。可以使用别名 OLD 和 NEW 来引用触发器中发生变化的记录内容,这与其他的数据库是相似的。现在触发器还只支持行级触发,不支持语句级触发。

4.1 创建触发器

  • 创建只有一个执行语句的触发器
create trigger 触发器名 before|after 触发事件
on 表名 for each row 
执行语句;
  • 创建有多个执行语句的触发器
create trigger 触发器名 before|after  触发事件 
on 表名 for each row
begin
     执行语句列表
end;

4.2 NEW与OLD

MySQL 中定义了 NEW 和 OLD,用来表示触发器的所在表中,触发了触发器的那一行数据,来引用触发器中发生变化的记录内容,具体地:

触发器类型 触发器类型NEW OLD的使用
INSERT 型触发器 NEW 表示将要或者已经新增的数据
UPDATE 型触发器 OLD 表示修改之前的数据 , NEW 表示将要或已经修改后的数据
DELETE 型触发器 OLD 表示将要或者已经删除的数据

4.3 查看和删除触发器

  • 查看触发器
show triggers;
  • 删除触发器
-- drop trigger [if exists] trigger_name 
drop trigger if exists trigger_test1;
  1. MYSQL中触发器中不能对本表进行 insert ,update ,delete 操作,以免递归循环触发

  2. 尽量少使用触发器,假设触发器触发每次执行1s,insert table 500条数据,那么就需要触发500次触发器,光是触发器执行的时间就花费了500s,而insert 500条数据一共是1s,那么这个insert的效率就非常低了。

  3. 触发器是针对每一行的;对增删改非常频繁的表上切记不要使用触发器,因为它会非常消耗资源。

你可能感兴趣的:(04MySQL的视图、存储过程和触发器)