您的位置:首页 > 数据库 > MySQL

MySQL 5.0 新特征教程 触发器:第一讲

2011-03-07 19:59 483 查看
来源:网海拾贝

作者:mysql AB;翻译:陈朋奕

Conventions and Styles商定和编程气概

  每次我想要演示理论代码时,我会对mysql客户端的屏幕就泛起的代码终了调解,将字体改成Courier,使他们看起来与日常平凡文本纷歧样(让大年夜师区别法式代码和注释)。在这里举个例子:

mysql> DROP FUNCTION f;
Query OK, 0 rows affected (0.00 sec)

  如果实例比力大年夜,则须要在某些行和段落间加注释,同时我会用将"<--"符号放在页面的左边以走漏施展分析夸张。比如:

mysql> CREATE PROCEDURE p ()
-> BEGIN
-> /* This procedure does nothing */ <--
-> END;//
Query OK, 0 rows affected (0.00 sec)

  偶然分我会将例子中的"mysql>"和"->"这些体系施展分析去失,你可以间接将代码复制到mysql客户端法式中(如果你现在所读的不是电子版的,可以在mysql.com网站下载相关脚本)

  所以的例子都曾经在Suse 9.2 Linux、Mysql 5.0.3大众版上测试议决。在您阅读本书的时分,Mysql曾经有更高的版本,同时能支撑更多OS了,包罗Windows,Sparc,HP-UX。是以这里的例子将能正常的运转在您的电脑上。但如果运转依然泛起流毒,可以咨询你邃晓的资深Mysql用户,这样就能失失比力好的支撑和帮助。

Why Triggers 为什么要用触发器

  我们在MySQL 5.0中包含对触发器的支撑是由于以下缘由:

  MySQL晚期版本的用户且自有须要触发器的要求。
  我们曾经应许支撑统统ANSI类型的特征。
  您可以运用它来搜检或戒备坏的数据进入数据库。
  您可以改动或许作废INSERT, UPDATE以及DELETE语句。
  您可以在一个会话中看守数据改动的举措。

  在这里我假定大年夜师都读过"MySQL新特征"丛书的第一集--"MySQL存储历程",那么大年夜师都应该知道MySQL至此存储历程和函数,那是很紧张的常识,由于在触发器中你可以运用在函数中运用的语句。稀疏举个例子:

  复合语句(BEGIN / END)是合理的.

  流节制(Flow-of-control)语句(IF, CASE, WHILE, LOOP, WHILE, REPEAT, LEAVE,ITERATE)也是合理的.

  变量声明(DECLARE)以及指派(SET)是合理的.

  允许条件声明.

  稀罕极度处置嘉奖声明也是允许的.

  然则在这里要记住函数有受限条件:不能在函数中会晤表.是以在函数中运用以下语句是合理的。

ALTER 'CACHE INDEX' CALL COMMIT CREATE DELETE

DROP 'FLUSH PRIVILEGES' GRANT INSERT KILL

LOCK OPTIMIZE REPAIR REPLACE REVOKE

ROLLBACK SAVEPOINT 'SELECT FROM table'

'SET system variable' 'SET TRANSACTION'

SHOW 'START TRANSACTION' TRUNCATE UPDATE

  在触发器中也有完全一样的限定.

  触发器相对而言比力新,是以会有(bugs)缺陷.所以我在这里给大年夜师申饬,就像我在存储历程书中所说那样.不要在含有紧张数据的数据库中运用这个触发器,如果须要的话在一些以测试为目的的数据库上运用,同时在你对表创建触发器时确认这些数据库是默许的。

Syntax 语法

  1. Syntax: Name 语法:定名端正

CREATE TRIGGER <触发器称号> <--
{ BEFORE | AFTER }
{ INSERT | UPDATE | DELETE }
ON <表称号>
FOR EACH ROW
<触发器SQL语句>

  触发器必需著名字,最多64个字符,可从前面会附有分隔符.它和MySQL中其他工具的定名编制基究竟象.

  这里我有个习气:就是用表的名字+'_'+触发器类型的缩写.是以如果是表t26,触发器是在变乱UPDATE(参考上面的点(2)和(3))之前(BEFORE)的,那么它的名字就是t26_bu。

  2. Syntax: Time 语法:触发光阴

CREATE TRIGGER <触发器称号>
{ BEFORE | AFTER } <--
{ INSERT | UPDATE | DELETE }
ON <表称号>
FOR EACH ROW
<触发的SQL语句>

  触发器有实行的光阴设置:可以设置为变乱发作前或后。

  3. Syntax: Event语法:变乱

CREATE TRIGGER <触发器称号>
{ BEFORE | AFTER }
{ INSERT | UPDATE | DELETE } <--
ON <表称号>
FOR EACH ROW
<触发的SQL语句>

  异样也能设定触发的变乱:它们可以在实行insert、update或delete的历程中触发。

  4. Syntax: Table 语法:表

CREATE TRIGGER <触发器称号>
{ BEFORE | AFTER }
{ INSERT | UPDATE | DELETE }
ON <表称号> <--
FOR EACH ROW
<触发的SQL语句>

  触发器是属于某一个表的:当在这个表上实行拔出、更新或删除操纵的时分就招致触发器的激活.
我们不能给同一张表的同一个变乱安排两个触发器。

  5. Syntax: Granularity 语法:( :( 步长)触发阻遏

CREATE TRIGGER <触发器称号>
{ BEFORE | AFTER }
{ INSERT | UPDATE | DELETE }
ON <表称号>
FOR EACH ROW <--
<触发的SQL语句>

  触发器的实行阻遏:FOR EACH ROW子句通知触发器每隔一行实行一次举措,而不是对整个表实行一次。

  6. Syntax: Statement 语法:语句

CREATE TRIGGER <触发器称号>
{ BEFORE | AFTER }
{ INSERT | UPDATE | DELETE }
ON <表称号>
FOR EACH ROW
<触发的SQL语句> <--

  触发器包含所要触发的SQL语句:这里的语句可所以任何合理的语句,包罗复合语句,然则这里的语句受的限定和函数的一样。

Privileges权限

  你必需拥有相称大年夜的权限技巧创建触发器(CREATE TRIGGER)。如果你曾经是Root用户,那么就充沛了。这跟SQL的类型有所不同,我也渴想能尽快改成类型的。

  是以在下一个版本的MySQL中,你完全有可以看到有一种叫做CREATE TRIGGER的新权限。然后议决这样的编制赋予:

GRANT CREATE TRIGGER ON <表称号> TO <用户或用户列表>;

  也可以议决这样发出权限:

REVOKE CREATE TRIGGER ON <表称号> FROM <用户或用户列表>;

Referring to OLD and NEW columns 关于旧的和新创建的列的标识

  在触发器的SQL语句中,你可以联络关系表中的随意任性列。但你不能仅运用列的称号去标识,那会使体系混杂,由于那里可以会有列的新名(这可以恰是你要改削的,你的举措可以恰是要改削列名),另有列的旧名存在。是以你必需用这样的语法来标识:

  "NEW . column_name"或许"OLD . column_name".这样在技术上处置嘉奖(NEW | OLD . column_name)新和旧的列名属于创建了过渡变量("transition variables")。

  马虎INSERT语句,只要NEW是合理的;马虎DELETE语句,只要OLD才合理;而UPDATE语句可以在和NEW以及OLD同时运用。上面是一个UPDATE中同时运用NEW和OLD的例子。

CREATE TRIGGER t21_au
BEFORE UPDATE ON t22
FOR EACH ROW
BEGIN
SET @old = OLD . s1;
SET @new = NEW.s1;
END;//

  现在如果t21表中的s1列的值是55,那么实行了"UPDATE t21 SET s1 = s1 1"之后@old的值会酿成55,而@new的值将会酿成56。

Example of CREATE and INSERT CREATE和INSERT的例子

  CREATE table with trigger创建有触发器的表

  这里统统的例程中我都假定大年夜师的分隔符曾经设置成//(DELIMITER //)。

CREATE TABLE t22 (s1 INTEGER)//

CREATE TRIGGER t22_bi
BEFORE INSERT ON t22
FOR EACH ROW
BEGIN
SET @x = 'Trigger was activated!';
SET NEW.s1 = 55;
END;//

  在最最先我创建了一个名字为t22的表,然后在表t22上创建了一个触发器t22_bi,当我们要向表中的行拔出时,触发器就会被激活,实行将s1列的值改为55的举措。

  INSERT on table w ith a trigger运用触发器实行拔出举措

mysql> INSERT INTO t22 VALUES (1)//

  让我们看如果向表t2中拔出一行数据触发器对应的表会怎样样?

  这里的拔出的举措是很罕有的,我们不须要触发器的权限来实行它。甚至不须要知道可否有触发器联络关系。

mysql> SELECT @x, t22.* FROM t22//
------------------------ ------
| @x | s1 |
------------------------ ------
| Trigger was activated! | 55 |
------------------------ ------
1 row in set (0.00 sec)

  大年夜师可以看到INSERT举措之后的结局,和我们预期的一样,x符号被改动了,同时这里拔出的数据不是我们最先输入的拔出数据,而是触发器本人的数据。

Example of a "check" constraint
"check"完好性束缚例子

  What's a "check" constraint 什么是"check"束缚

  在类型的SQL言语中,我们可以在(CREATE TABLE)创建表的历程中运用"CHECK (condition)",
比如:

CREATE TABLE t25
(s1 INT, s2 CHAR(5), PRIMARY KEY (s1),
CHECK (LEFT(s2,1)='A'))
ENGINE=INNODB;

  这里CHECK的意思是"当s2列的最左边的字符不是'A'时,insert和update语句都会集理",MySQL的视图不支撑CHECK,我团体是很渴想它能支撑的。但如果你很须要在表中运用这样的功用,我建议大年夜师运用触发器来完成。

CREATE TABLE t25
(s1 INT, s2 CHAR(5),
PRIMARY KEY (s1))
ENGINE=INNODB//

CREATE TRIGGER t25_bi
BEFORE INSERT ON t25
FOR EACH ROW
IF LEFT(NEW.s2,1)<>'A' THEN SET NEW.s1=0; END IF;//

CREATE TRIGGER t25_bu
BEFORE UPDATE ON t25
FOR EACH ROW
IF LEFT(NEW.s2,1)<>'A' THEN SET NEW.s1=0; END IF;//

  我只须要运用BEFORE INSERT和BEFORE UPDATE语句就行了,删除了触发器不会对表有影响,同时AFTER的触发器也不能改削NEW的历程变量(transition variables)。为了激活触发器,我实行了向表中的行拔出s1=0的数据,之后只需实行切合LEFT(s2,1) <> 'A'条件的举措都会失败:

INSERT INTO t25 VALUES (0,'a') /* priming the pump */ //
INSERT INTO t25 VALUES (5,'b') /* gets error '23000' */ //

Don't Believe The Old MySQL Manual
该抛弃旧的MySQL的手册了

  我在这里申饬大年夜师不要相信已往的MySQL手册中所说的了。我们曾经去失了关于触发器的错误的语句,然则模仿还是有很多旧版本的手册在网上,举个例子,这是一个德国的Url上的:

  http://dev.mysql.com/doc/mysql/de/ANSI_diff_Triggers.html.

  这个手册上说触发器就是存储历程,忘失吧,你也曾经看见了,触发器就是触发器,而存储历程还是存储历程。

  手册上还说触发器可以从其他表下去删除,或许是当你删除一个事件的时分激起,无论他说的是什么意思,忘失吧,MySQL不会去完成这些的。

  最后关于说运用触发器会对究诘速率发作影响的说法也是错的,触发器不会对究诘发作任何影响。

  Bugs
  (不好的工具就不翻译了)
  On December 14 2004, I did an "Advanced Search" in http://bugs.mysql.com for 'trigger' or
  'triggers', I found that there were 17 active bugs as of that date. Of course they might disappear
  before you read this, but just in case they haven't, I'll mention the important ones. If they're still
  there, you'll have to work around them when you're trying triggers.

  Bug#5859 DROP TABLE does not drop triggers.
  (删除表的时分没有自动删除触发器)
  When you drop a table, dropping the table's triggers should be automatic.

  Bug#5892 Triggers have the wrong namespace.
  (触发器的定名空间有错,你必需在前面加上表的名字技巧删除触发器,上面是例子)
  You have to say "DROP TRIGGER <table name> . <trigger name>".
  The correct way is "DROP TRIGGER <trigger name>".

  Bug#5894 Triggers with altered tables cause corrupt databases.
  (触发器对表的改动可以会构成数据库数据被破碎摧毁)
  Do not alter a table that has a trigger on it, until you know this is fixed.

Conclusion 最后

  到了书的最后,我认为不须要给大年夜师复习或许是重温一下了,由于相信大年夜师可以很轻松的记住上面所说的。

版权声明:
原创作品,允许转载,转载时请务必以超链接情势标明文章 原始来由 、作者信息和本声明。不然将追查执法责任。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: