首页 热点资讯 义务教育 高等教育 出国留学 考研考公
您的当前位置:首页正文

mysql之触发器

2023-11-09 来源:华佗小知识

    MySQL语句在需要时被执行,存储过程也是如此。但是,如果你想要某条语句(或某些语句)在事件发生时自动执行,怎么办呢?例如:每当增加一个顾客到某个数据库表时,都检查其电话号码格式是否正确,州的缩写是否为大写;每当订购一个产品时,都从库存数量中减去订购的数量;无论何时删除一行,都在某个存档表中保留一个副本。    所有这些例子的共同之处是它们都需要在某个表发生更改时自动处理某个动作。这确切地说就是一个触发器。 触发器是MySQL 响应以下任意语句而自动执行任意其他的一条 MySQL语句(或位于BEGIN和 END语句之间的一组语句)        1、DELECT        2、INSERT        3、UPDATE其他的mysql语句不支持触发器的。 创建触发器    在创建触发器时,需要给出 4条信息:        1、唯一的触发器名;        2、触发器关联的表        3、触发器应该响应的动作( DELETE、INSERT 或UPDATE)        4、触发器何时执行(处理之前或之后)。    注意:保持每个数据库的触发器名唯一。    触发器用 CREATE TRIGGER语句创建。下面是一个简单的例子:
mysql> DELIMITER //mysql> CREATE TRIGGER newproduct AFTER INSERT ON products -> FOR EACH ROW -> SELECT ‘added ‘ INTO @ee; -> //Query OK, 0 rows affected (0.05 sec)
    CREATE TRIGGER用来创建名为newproduct的新触发器。触发器可在一个操作发生之前或之后执行,这里给出了 AFTER INSERT,所以此触发器将在 INSERT语句成功执行后执行。FOR EACH ROW是触发器的执行间隔,FOR EACH ROW子句通知触发器每隔一行执行一次动作,而不是对整个表执行一次。在这个例子中,文本 added将对每个插入的行显示一次。为了测试这个触发器,使用 INSERT语句添加一行或多行到products中,你将看到对每个成功的插入。
mysql> insert into products (prod_id, vend_id, prod_name, prod_price, prod_desc) -> values -> (‘TNT3‘, 1002, ‘liwei‘, 123.12, ‘dudu jiushi ni‘) -> //Query OK, 1 row affected (0.03 sec)
    在使用select来查询变量ee,看看结果是什么
select @ee//
    结果是:
+------+| @ee |+------+| added |+------+
    注意:只有表才支持触发器,视图不支持(临时表也不支持)。    触发器按每个表每个事件每次地定义,每个表每个事件每次只允许一个触发器。因此,每个表最多支持 6个触发器(每条INSERT、 UPDATE和DELETE的之前和之后)。单一触发器不能与多个事件或多个表关联,所以,如果你需要一个对 INSERT和UPDATE 操作执行的触发器,则应该定义两个触发器。    注意:如果BEFORE触发器失败,则 MySQL将不执行请求的操作。此外,如果 BEFORE触发器或语句本身失败, MySQL将不执行 AFTER触发器(如果有的话)。 删除触发器    现在,删除触发器的语法应该很明显了。为了删除一个触发器,可使用 DROP TRIGGER语句,如下所示:
DROP TRIGGER newproduct 
    触发器不能更新或覆盖。为了修改一个触发器,必须先删除它,然后再重新创建。 使用触发器    在有了前面的基础知识后,我们现在来看所支持的每种触发器类型以及它们的差别。 INSERT触发器    INSERT触发器在INSERT 语句执行之前或之后执行。需要知道以下几点:        1、在INSERT触发器代码内,可引用一个名为 NEW的虚拟表,访问被插入的行。        2、在BEFORE INSERT触发器中, NEW中的值也可以被更新(允许更改被插入的值);        3、对于 AUTO_INCREMENT列,NEW 在INSERT执行之前包含 0,在INSERT执行之后包含新的自动生成值。    下面举一个例子(一个实际有用的例子)。 AUTO_INCREMENT列具有MySQL自动赋予的值。第21章建议了几种确定新生成值的方法,但下面是一种更好的方法:
mysql> create trigger neworder after insert on orders -> for each row select new.order_num into @liwei;
    此代码创建一个名为 neworder的触发器,它按照AFTER INSERTON orders执行。在插入一个新订单到 orders表时,MySQL 生成一个新订单号并保存到 order_num中。触发器利用select 语句的返回结果,从NEW. order_num取得这个值并赋值给变量liwei。此触发器必须按照 AFTER INSERT执行,因为在BEFORE INSERT语句执行之前,新order_num还没有生成。对于 orders的每次插入使用这个触发器将总是返回新的订单号。接着我们插入新的数据看看。
mysql> insert into orders(order_date,cust_id) -> values (Now(), 10001);
    数据插入完成之后,我们来使用liwei变量来查询新的订单号。
mysql> select @liwei;
    结果:
+--------+| @liwei |+--------+| 20010 |+--------+1 row in set (0.02 sec)
    orders 表包含3 个列。order_date 和 cust_id 必须给出,order_num由MySQL 自动生成,而现在 order_num 输出赋值给一个变量。然后利用这个变量做返回。通常,将 BEFORE 用于数据验证和净化(目的是保证插入表中的数据确实是需要的数据)。本提示也适用于 UPDATE触发器。 DELETE触发器    DELETE 触发器在DELETE 语句执行之前或之后执行。需要知道以下两点:        1、在 DELETE触发器代码内,你可以引用一个名为 OLD 的虚拟表,访问被删除的行;        2、OLD 中的值全都是只读的,不能更新。    下面的例子演示使用 OLD 保存将要被删除的行到一个存档表中:
mysql> create trigger deleteorder before delete on orders -> for each row select old.order_num,old.order_date into @liwei,@tx;
    删除一条数据:
mysql> delete from orders where order_num = 10002;Query OK, 1 row affected (0.14 sec)
    我们来看看查询上面声明的两个变量(liwei与tx)
mysql> select @liwei;
    输出:
+--------+| @liwei |+--------+| 10002 |+--------+
    或者是如下语句一条数据。
create trigger deleteorder before delete on ordersfor each row begininsert into otherorder (order_num, prder, cust_id) values( old.order_num, old.order_date, old.cust_id);
    在任意订单被删除前将执行此触发器。它使用一条 INSERT 语句将 OLD中的值(要被删除的订单)保存到一个名为 otherorder的存档表中(为实际使用这个例子,你需要用与 orders 相同的列创建一个名为 otherorder的表)。    使用 BEFORE DELETE 触发器的优点(相对于 AFTER DELETE触发器来说)为,如果由于某种原因,订单不能存档, DELETE 本身将被放弃。    正如所见,触发器 deleteorder 使用BEGIN 和END 语句标记触发器体。这在此例子中并不是必需的,不过也没有害处。使用 BEGIN END 块的好处是触发器能容纳多条 SQL语句(在 BEGIN END 块中一条挨着一条)。 UPDATE触发器    UPDATE 触发器在UPDATE 语句执行之前或之后执行。需要知道以下几点:        1、在 UPDATE触发器代码中,你可以引用一个名为 OLD 的虚拟表访问以前( UPDATE 语句前)的值,引用一个名为 NEW 的虚拟表访问新更新的值;        2、在 BEFORE UPDATE触发器中, NEW 中的值可能也被更新(允许更改将要用于 UPDATE 语句中的值);        3、OLD 中的值全都是只读的,不能更新。    下面的例子保证州名缩写总是大写(不管 UPDATE 语句中给出的是大写还是小写):
mysql> create trigger upvendor before update on vendors -> for each row set new.vend_state = upper(new.vend_state);Query OK, 0 rows affected (0.21 sec)
    显然任何数据净化都需要在update语句之前进行。就像这个例子中的一样。每次在更新一行时, NEW.vend_state中的值(将用来更新表行的值)都用 Upper(NEW.vend_state) 替换。 关于触发器的进一步介绍    1、创建触发器可能需要特殊的安全访问权限,但是,触发器的执行是自动的。如果 INSERT 、UPDATE 或 DELETE语句能够执行,则相关的触发器也能执行。    2、应该用触发器来保证数据的一致性(大小写、格式等)。在触发器中执行这种类型的处理的优点是它总是进行这种处理,而且是透明地进行,与客户机应用无关。    3、触发器的一种非常有意义的使用是创建审计跟踪。使用触发器,把更改(如果需要,甚至还有之前和之后的状态)记录到另一个表非常容易。    4、遗憾的是, MySQL 触发器中不支持 CALL语句。这表示不能从触发器内调用存储过程。所需的存储过程代码需要复制到触发器内。     关于什么时候使用new,old这两个关键字就好像字面意思新旧一样:         INSERT 只有NEW        UPDATE既有NEW又和OLD        DELETE只有OLD     所以对于INSERT语句,只有NEW是合法的;对于DELETE语句,只有OLD才合法;而UPDATE语句可以在和NEW以及 OLD同时使用。下面是一个UPDATE中同时使用NEW和OLD的例子。 
CREATE TRIGGER tr1 BEFORE UPDATE ON liwei FOR EACH ROW BEGIN SET @old = OLD.s1; SET @new = NEW.s1; END; 
    现在如果liwei表中的s1列的值是55,也就是@new的值就是55,那么执行了"UPDATE liwei SET s1 = s1 + 1"之后@old的值会变成55,     另外按照我在使用trigger和function的时候在mysql的trigger和function中不能出现select * from table形式的查询,因为其会返回一个结果集;而这在mysql的trigger和function中是不可接受的,但是在存储过程中可以。在 trigger和function中可以使用select ... into ...形式的查询。比如在使用trigger的时候没有into 的时候会报这样一种错误:
not allowed to return a result set from a trigger

 

mysql之触发器

标签:

小编还为您整理了以下内容,可能对您也有帮助:

mysql触发器(MySQL触发器(定义、使用及示例))

MySQL触发器是一种特殊的存储过程,它是由MySQL服务器自动执行的一种数据库对象。当指定的事件发生时,触发器会被激活并执行相应的操作。这些事件可以是INSERT、UPDATE或DELETE语句的执行,也可以是表的创建或删除。MySQL触发器可以用于实现数据的自动更新、数据的验证和数据的审计等功能。

MySQL触发器的定义

MySQL触发器的定义包含以下几个部分:

1.触发器的名称:用于标识触发器的名称。

2.触发器的事件:触发器所要监控的事件,可以是INSERT、UPDATE或DELETE语句的执行,也可以是表的创建或删除。

3.触发器所在的表:触发器所要监控的表。

4.触发器的执行时间:触发器所要执行的时间,可以是BEFORE或AFTER。

5.触发器的执行语句:触发器所要执行的SQL语句。

MySQL触发器的使用

下面是一个MySQL触发器的示例:

```

CREATETRIGGER`trigger_name`BEFOREINSERTON`table_name`

FOREACHROWBEGIN

--触发器所要执行的SQL语句

END;

```

触发器的名称为`trigger_name`,它所要监控的事件是INSERT语句的执行,它所在的表为`table_name`,它所要执行的时间是BEFORE,它所要执行的SQL语句可以在BEGIN和END之间编写。

MySQL触发器的示例

下面是一个MySQL触发器的示例,该触发器在每次向`employee`表中插入新记录时,自动更新`department`表中的员工人数。

```

CREATETRIGGER`update_department_count`

AFTERINSERTON`employee`

FOREACHROWBEGIN

UPDATE`department`SET`count`=`count`+1WHERE`department_id`=NEW.`department_id`;

END;

```

该触发器的名称为`update_department_count`,它所要监控的事件是INSERT语句的执行,它所在的表为`employee`,它所要执行的时间是AFTER,它所要执行的SQL语句为UPDATE语句,它将`department`表中对应部门的员工人数加1。

MySQL触发器的注意事项

1.MySQL触发器只能在表级别上创建,不能在行级别上创建。

2.MySQL触发器可以使用NEW和OLD关键字来引用插入、更新或删除的行的值。

3.MySQL触发器可以使用IF和CASE语句来进行条件判断。

4.MySQL触发器可以使用RAISE_APPLICATION_ERROR函数来抛出异常。

mysql触发器怎么写

触发器是与 MySQL 数据表有关的数据库对象,在满足定义条件时触发,并执行触发器中定义的语句集合。触发器的这种特性可以协助应用在数据库端确保数据的完整性。

语法格式如下:

CREATE <触发器名> < BEFORE | AFTER >

<INSERT | UPDATE | DELETE >

ON <表名> FOR EACH Row<触发器主体>语法说明如下。

1) 触发器名

触发器的名称,触发器在当前数据库中必须具有唯一的名称。如果要在某个特定数据库中创建,名称前面应该加上数据库的名称。

2) INSERT | UPDATE | DELETE

触发事件,用于指定激活触发器的语句的种类。

注意:三种触发器的执行时间如下。INSERT:将新行插入表时激活触发器。例如,INSERT 的 BEFORE 触发器不仅能被 MySQL 的 INSERT 语句激活,也能被 LOAD DATA 语句激活。DELETE: 从表中删除某一行数据时激活触发器,例如 DELETE 和 REPLACE 语句。UPDATE:更改表中某一行数据时激活触发器,例如 UPDATE 语句。

3) BEFORE | AFTER

BEFORE 和 AFTER,触发器被触发的时刻,表示触发器是在激活它的语句之前或之后触发。若希望验证新数据是否满足条件,则使用 BEFORE 选项;若希望在激活触发器的语句执行之后完成几个或更多的改变,则通常使用 AFTER 选项。

4) 表名

与触发器相关联的表名,此表必须是永久性表,不能将触发器与临时表或视图关联起来。在该表上触发事件发生时才会激活触发器。同一个表不能拥有两个具有相同触发时刻和事件的触发器。例如,对于一张数据表,不能同时有两个 BEFORE UPDATE 触发器,但可以有一个 BEFORE UPDATE 触发器和一个 BEFORE INSERT 触发器,或一个 BEFORE UPDATE 触发器和一个 AFTER UPDATE 触发器。

5) 触发器主体

触发器动作主体,包含触发器激活时将要执行的 MySQL 语句。如果要执行多个语句,可使用 BEGIN?END 复合语句结构。

6) FOR EACH ROW

一般是指行级触发,对于受触发事件影响的每一行都要激活触发器的动作。例如,使用 INSERT 语句向某个表中插入多行数据时,触发器会对每一行数据的插入都执行相应的触发器动作。

注意:每个表都支持 INSERT、UPDATE 和 DELETE 的 BEFORE 与 AFTER,因此每个表最多支持 6 个触发器。每个表的每个事件每次只允许有一个触发器。单一触发器不能与多个事件或多个表关联。

另外,在 MySQL 中,若需要查看数据库中已有的触发器,则可以使用 SHOW TRIGGERS 语句。

例子:

BEGIN

IF new.state in ('2','3') then

INSERT INTO `userservice`.`ehome_us_green_examine`

(modifydate,modifyuser,brancCode,stateDescription,state,

userID,fromSystemkey,applydate,makeHospitalName,illnessName,

userName,rightsholderName,tranno)

VALUES ( sysdate(), 'manage', old.brancCode, old.stateDescription, new.state,

'', old.fromSystemkey, old.applydate,old.makeHospitalName,old.illnessName,

old.userName,old.rightsholderName, old.tranno);

END IF;

END这个触发器比较简单,

1、BEGIN到END,之间是对数据库的操作

2、IF到END IF之间是判断,你想的对,就是如果。。的意思

3、new.state in ('2','3') 这句的意思是:该表的字段state为(2或者3)的时候

4、执行下面的插入语句,new为新值,old是原来的值(如old.userName就是原来的这个字段的值)

5、整个触发器翻译成白话就是,如果该表的state变成2或者3的时候,执行下面的插入语句

备注:那么触发器是发生在状态变化之前还是之后呢?选Before或者After,顾名思义!

MySQL触发器可以基于在什么?

创建索引时使用什么参数可以索引所在字段不能重复?

MySQL触发器可以基于以下几种类型的行数据变更:

用户自定义变量:当用户在表中定义自定义变量时,可以通过UPDATE、INSERT或DELETE语句来修改或删除这些变量的值。触发器可以在这些语句的执行期间启动,当这些操作涉及到这些变量时,触发器会自动执行。

表级别变更:当表的结构发生变化(例如添加、删除或修改列)时,触发器可以在这些操作执行期间启动。当表级别的变更涉及到表中的行时,触发器会自动执行。

计划任务:可以使用MySQL的计划任务功能来设置定时任务,这些任务可以在指定的时间和日期自动执行。当任务涉及到表中的行时,触发器可以在任务执行期间启动,当任务涉及到这些行时,触发器会自动执行。

外部事件:可以使用MySQL的事件通知功能来捕获系统事件,例如数据库的插入、更新或删除操作。当事件发生时,触发器可以在事件通知的处理程序中启动,当事件涉及到这些行时,触发器会自动执行。

触发器可以基于这些类型的行数据变更来启动,当满足触发器条件时,触发器会自动执行。在实际应用中,可以根据需要灵活选择合适的触发器类型来实现自动化操作或处理数据变更。

显示全文