MySQL游标和触发器

1、游标

定义:是一个存储在MySQL服务器上的数据库查询,是一种被select语句检索出来的结果集。sql

做用:方便在检索出来的结果集中前进或后退一行或多行。数据库

PS游标主要用于交互式应用;MySQL中的游标只能用于存储过程(和函数)。安全

 

1、建立游标服务器

游标使用declare语句建立;declare命名游标,并定义相应的select语句,根据须要带where和其余子句;例如:函数

create procedure processorders()
begin
       declare ordernumbers CURSOR
       for
       select order_num from orders;
end;

这个存储过程当中,declare定义和命名了游标ordernumbers,存储过程处理完成后,游标就消失(局限于存储过程内)。oop

 

2、打开和关闭游标fetch

定义游标以后,能够打开它,用open cursor语句来打开,例如:open ordernumbers;spa

在处理open语句时执行查询,存储检索出的数据以供浏览和滚动;指针

游标处理完成时,用close语句关闭,例如:close ordernumbers;code

close释放游标使用的全部内部内存和资源,所以在每一个游标不在须要时都应该关闭。

PS

游标关闭后,若是没有从新打开,则不能使用;但若是该游标被声明过,则不须要再次声明,用open打开使用便可。

若是不明确游标是否关闭,MySQL将会在到达end语句时自动关闭该游标。

 

3、使用游标数据

游标被打开后,使用fetch语句分别访问它的每一行;fetch指定检索什么数据(所需的列),检索的数据存储在什么地方,还向前移动游标中的内部行指针,使下一条fetch语句检索下一行(不重复读取)。

检索第一行数据,例如:

create procedure processorders()
begin
       --declare local variables
       declare o int;

       --declare the cursor
       declare ordernumbers cursor for select order_num from orders;

       --open the cursor
       open ordernumbers;

       --get order number
       fetch ordernumbers into o;

       --close the cursor
       close ordernumbers;
end;

这条语句中fetch用来检索当前行的order_num列(自动从第一行开始)到一个名为o的局部声明变量中;对检索出的数据不作任何处理。

循环检索数据,从第一行到最后一行,以下:

create procedure processorders()  --建立存储过程
begin
       --declare local variables
       declare done boolean default 0;
       declare 0 int;

       --declare the cursor
       declare ordernumbers cursor
       for select order_num from orders;  --结果集

       --declare continue handler
       declare continue handler for sqlstate '02000' set done=1;  --在这里,done被设置为结束时为真

       --open the cursor
       open ordernumbers;

       --loop through all rows
       repeat

       --get order number
       fetch ordernumbers into o;

       --end of loop
       until done end repeat;

       --close the cursor
       close ordernumbers;
end;

与前一个例子同样,用fetch检索当前order_num到声明的o变量中。区别在于:这个例子中fetch是在repeat内,所以它反复执行到done为真(由until done end repeat;规定)。

在语句(declare continue handler for sqlstate '02000' set done=1;)中,定义了CONTINUE HANDLER,它是在条件出现时被执行的代码。当SQLSTATE '02000'出现时,SET done=1。

SQLSTATE '02000'是一个未找到条件,当REPEAT因为没有更多的行供循环而不能继续时,出现这个条件。done被设置为真。

PS

用declare语句定义的局部变量必须在定义任意游标或句柄以前定义,而句柄必须在游标以后定义。

MySQL还支持循环语句,它可用来重复执行代码,直到使用leave语句手动退出为止;一般repeat语句的语法使它更适合于对游标进行循环。

 

4、使用游标的几个注意事项

一、在使用游标前,必须声明(定义)它;这个过程实际没有检索数据,只是定义要使用的select语句;

二、一旦声明,则必须打开游标以供使用(这个过程用前面定义的select语句把数据实际检索出来);

三、对于填有数据的游标,根据须要取出(检索)各行;

四、结束游标使用时,必须关闭游标。

 

2、触发器

MySQL语句在须要时被执行,存储过程也是如此,若是但愿某条语句(或某些语句)在事件发生时自动执行,这就须要用到触发器。

触发器是MySQL响应如下任意语句而自动执行的一条MySQL语句(或位于begin和end语句之间的一组语句):delete;insert;update。其余MySQL语句不支持触发器。

 

1、建立触发器

须要的信息:惟一的触发器名;触发器关联的表;触发器应该响应的活动(delete、insert或update);触发器什么时候执行(处理以前或以后)。

PSMySQL中,触发器名必须在每一个表中惟一,但不是在每一个数据库中惟一。即:同一数据库中两个表能够具备相同名字的触发器,但其余的DBMS中不被容许,因此最好是在数据库范围内使用惟一的触发器名。

触发器使用create teigger语句建立,如:

create trigger newproduct after insert on products
for each row select 'product added';

建立newproduct触发器,给出了after insert,因此此触发器在insert语句成功执行后执行;还指定了for each row,所以代码对每一个插入行执行。

PS

一、只有表才支持触发器,视图不支持(临时表也不支持)。

二、触发器按每一个表每一个事件每次的定义,每一个表每一个事件每次只容许一个触发器;所以每一个表最多支持6个触发器(每条insert、update和delete的以前和以后),单一触发器不能与多个事件或多个表关联。

三、若是before触发器失败,则MySQL将不执行请求的操做;此外,若是before触发器或语句自己失败,MySQL将不执行after触发器(若是有的话)。

 

2、删除触发器

删除触发器用drop trigger语句,如:

drop trigger newproduct;

PS触发器不能更新或覆盖;为了修改一个触发器,必须先删再建。

 

3、使用触发器

1、insert触发器

使用insert触发器,须要知道如下三点:

一、在insert触发器代码内,可引用一个名为new的虚拟表,访问被插入的行;

二、在before insert触发器内,new中的值也能够被更新(容许更改被插入的值);

三、对于auto increment列,new在insert执行以前包含0,在insert执行以后包含新的自动生成值;

对于AUTO_INCREMENT自动赋予的值,肯定新生成值的方法,例子以下:

create trigger neworder after insert on orders
for each row select new.order_num;

建立一个名为neworder的触发器,按照after insert on order执行;在插入一条新的数据到orders表时,MySQL生成一个新订单号并保存到order_num中;

触发器从new.order_num取这个值并返回它;此触发器必须按照after insert执行,由于在before insert语句执行以前,新order_num还没生成。

PS一般将before用于数据验证和净化(目的是保证插入表中的数据确实是须要的数据)。这个规则也适用于update触发器。

 

2、delete触发器

使用delete触发器,须要知道如下两点:

一、在delete触发器代码内,能够引用一个名为old的虚拟表,访问被删除的行;

二、old中的值全都是只读的,不能更新;

使用old保存将要被删除的行到一个存档表中:

create trigger deleteorder before delete on orders
for each row
begin
    insert into archive_orders(order_num,order_date,cust_id)
    values(OLD_order_num, OLD_order_date, OLD_cust_id);
end;

在任意数据被删除前执行此触发器;它使用insert语句将old中的值(要被删除的数据)保存到一个名为archive_orders的存档表中;

PS使用begin end块的好处是触发器能容纳多条SQL语句。

 

3、update触发器

使用update触发器,须要知道如下三点:

一、在update触发器代码内,能够引用一个名为old的虚拟表访问之前(update语句前)的值,引用一个名为new的虚拟表访问新更新的值;

二、在before update触发器中,new中的值可能也被更新(容许更改将要用于update语句中的值);

三、old中的值全都是只读的,不能更新;

下面的例子,保证了州名称缩写老是大写:

create trigger updateevendor before update on vendors
for each row set new.vend_state = upper(new.vend_state);

每次更新一个行时,new.vend_state中的值都用upper(new.vend_state)替换。

 

4、关于触发器一些必须知道的知识:

一、建立触发器可能须要特殊的安全访问权限,但触发器的执行是自动的。若是insert、update或delete语句能够执行,则相应触发器也能执行;

二、应该用触发器来保证数据的一致性(大小写、格式等);优势在于它老是进行这种处理,并且是透明的进行,与客户机应用无关;

三、触发器的一种很是有意义的使用是建立审计跟踪。使用触发器,把更改记录到另外一个表很是容易;

四、MySQL触发器不支持call语句,即不能从触发器内调用存储过程。所需的存储过程代码须要复制到触发器内。

相关文章
相关标签/搜索