仓酷云

 找回密码
 立即注册
搜索
热搜: 活动 交友 discuz
查看: 763|回复: 8
打印 上一主题 下一主题

[学习教程] 公布MySQL 5.0 新特征教程 触发器:第一讲

[复制链接]
活着的死人 该用户已被删除
跳转到指定楼层
楼主
发表于 2015-1-16 20:09:04 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
如果你在一个遵循GPL的自由(开源)项目中使用MySQL,那么你可以遵循GPL协议使用MySQL。然而,如果你的项目不是在GPL协议下的话,你必须为使用MySQL来支付许可费用,或者你可能因为这个因素而将你的项目改为遵循GPL。MySQLAB;翻译:陈朋奕
ConventionsandStyles商定和编程作风
  每次我想要演示实践代码时,我会对mysql客户真个屏幕就呈现的代码举行调剂,将字体改成Courier,使他们看起来与一般文本纷歧样(让人人区分程序代码和注释)。在这里举个例子:

mysql>DROPFUNCTIONf;
QueryOK,0rowsaffected(0.00sec)
  假如实例对照年夜,则必要在某些行和段落间加正文,同时我会用将"<--"标记放在页面的右侧以暗示夸大。比方:

mysql>CREATEPROCEDUREp()
->BEGIN
->/*Thisproceduredoesnothing*/<--
->END;//
QueryOK,0rowsaffected(0.00sec)
  偶然候我会将例子中的"mysql>"和"->"这些体系显现往失落,你能够间接将代码复制到mysql客户端程序中(假如你如今所读的不是电子版的,能够在mysql.com网站下载相干剧本)
  以是的例子都已在Suse9.2linux、Mysql5.0.3大众版上测试经由过程。在您浏览本书的时分,Mysql已有更高的版本,同时能撑持更多OS了,包含Windows,Sparc,HP-UX。因而这里的例子将能一般的运转在您的电脑上。但假如运转仍旧呈现妨碍,能够征询你熟悉的资深Mysql用户,如许就可以失掉对照好的撑持和匡助。
WhyTriggers为何要用触发器
  我们在MySQL5.0中包括对触发器的撑持是因为以下缘故原由:
  MySQL初期版本的用户临时有必要触发器的请求。
  我们已经允诺撑持一切ANSI尺度的特征。
  您可使用它来反省或防备坏的数据进进数据库
  您能够改动大概作废INSERT,UPDATE和DELETE语句。
  您能够在一个会话中监督数据改动的举措。
  在这里我假定人人都读过"MySQL新特征"丛书的第一集--"MySQL存储历程",那末人人都应当晓得MySQL至此存储历程和函数,那是很主要的常识,由于在触发器中你可使用在函数中利用的语句。出格举个例子:
  复合语句(BEGIN/END)是正当的.
  流把持(Flow-of-control)语句(IF,CASE,WHILE,LOOP,WHILE,REPEAT,LEAVE,ITERATE)也是正当的.
  变量声明(DECLARE)和指派(SET)是正当的.
  同意前提声明.
  非常处置声明也是同意的.
  可是在这里要记着函数有受限前提:不克不及在函数中会见表.因而在函数中利用以下语句长短法的。

ALTERCACHEINDEXCALLCOMMITCREATEDELETE
DROPFLUSHPRIVILEGESGRANTINSERTKILL
LOCKOPTIMIZEREPAIRREPLACEREVOKE
ROLLBACKSAVEPOINTSELECTFROMtable
SETsystemvariableSETTRANSACTION
SHOWSTARTTRANSACTIONTRUNCATEUPDATE
  在触发器中也有完整一样的限定.
  触发器绝对而言对照新,因而会有(bugs)缺点.以是我在这里给人人告诫,就像我在存储历程书中所说那样.不要在含有主要数据的数据库中利用这个触发器,假如必要的话在一些以测试为目标的数据库上利用,同时在你对表创立触发器时确认这些数据库是默许的。
Syntax语法
  1.Syntax:Name语法:定名划定规矩

CREATETRIGGER<触发器称号><--
{BEFORE|AFTER}
{INSERT|UPDATE|DELETE}
ON<表称号>
FOREACHROW
<触发器SQL语句>
  触发器必需着名字,最多64个字符,大概前面会附有分开符.它和MySQL中其他工具的定名体例基础相象.
  这里我有个习气:就是用表的名字+_+触发器范例的缩写.因而假如是表t26,触发器是在事务UPDATE(参考上面的点(2)和(3))之前(BEFORE)的,那末它的名字就是t26_bu。

  2.Syntax:Time语法:触发工夫

CREATETRIGGER<触发器称号>
{BEFORE|AFTER}<--
{INSERT|UPDATE|DELETE}
ON<表称号>
FOREACHROW
<触发的SQL语句>
  触发器有实行的工夫设置:能够设置为事务产生前或后。
  3.Syntax:Event语法:事务

CREATETRIGGER<触发器称号>
{BEFORE|AFTER}
{INSERT|UPDATE|DELETE}<--
ON<表称号>
FOREACHROW
<触发的SQL语句>
  一样也能设定触发的事务:它们能够在实行insert、update或delete的过程当中触发。
  4.Syntax:Table语法:表

CREATETRIGGER<触发器称号>
{BEFORE|AFTER}
{INSERT|UPDATE|DELETE}
ON<表称号><--
FOREACHROW
<触发的SQL语句>
  触发器是属于某一个表的:当在这个表上实行拔出、更新或删除操纵的时分就招致触发器的激活.
我们不克不及给统一张表的统一个事务布置两个触发器。
  5.Syntax:Granularity语法:(:(步长)触发距离

CREATETRIGGER<触发器称号>
{BEFORE|AFTER}
{INSERT|UPDATE|DELETE}
ON<表称号>
FOREACHROW<--
<触发的SQL语句>
  触发器的实行距离:FOREACHROW子句关照触发器每隔一行实行一次举措,而不是对全部表实行一次。
  6.Syntax:Statement语法:语句

CREATETRIGGER<触发器称号>
{BEFORE|AFTER}
{INSERT|UPDATE|DELETE}
ON<表称号>
FOREACHROW
<触发的SQL语句><--
  触发器包括所要触发的SQL语句:这里的语句能够是任何正当的语句,包含复合语句,可是这里的语句受的限定和函数的一样。
Privileges权限
  你必需具有相称年夜的权限才干创立触发器(CREATETRIGGER)。假如你已是Root用户,那末就充足了。这跟SQL的尺度有所分歧,我也但愿能尽快改成尺度的。
  因而鄙人一个版本的MySQL中,你完整有大概看到有一种叫做CREATETRIGGER的新权限。然后经由过程如许的办法付与:

GRANTCREATETRIGGERON<表称号>TO<用户或用户列表>;
  也能够经由过程如许发出权限:

REVOKECREATETRIGGERON<表称号>FROM<用户或用户列表>;
ReferringtoOLDandNEWcolumns关于旧的和新创立的列的标识
  在触发器的SQL语句中,你能够联系关系表中的恣意列。但你不克不及仅利用列的称号往标识,那会使体系搅浑,由于那边大概会有列的新名(这大概恰是你要修正的,你的举措大概恰是要修正列名),另有列的旧名存在。因而你必需用如许的语法来标识:
  "NEW.column_name"大概"OLD.column_name".如许在手艺上处置(NEW|OLD.column_name)新和旧的列名属于创立了过渡变量("transitionvariables")。
  关于INSERT语句,只要NEW是正当的;关于DELETE语句,只要OLD才正当;而UPDATE语句能够在和NEW和OLD同时利用。上面是一个UPDATE中同时利用NEW和OLD的例子。

CREATETRIGGERt21_au
BEFOREUPDATEONt22
FOREACHROW
BEGIN
SET@old=OLD.s1;
SET@new=NEW.s1;
END;//
  如今假如t21表中的s1列的值是55,那末实行了"UPDATEt21SETs1=s1+1"以后@old的值会酿成55,而@new的值将会酿成56。
ExampleofCREATEandINSERTCREATE和INSERT的例子
  CREATEtablewithtrigger创立有触发器的表
  这里一切的例程中我都假定人人的分开符已设置成//(DELIMITER//)。

CREATETABLEt22(s1INTEGER)//
CREATETRIGGERt22_bi
BEFOREINSERTONt22
FOREACHROW
BEGIN
SET@x=Triggerwasactivated!;
SETNEW.s1=55;
END;//
  在最入手下手我创立了一个名字为t22的表,然后在表t22上创立了一个触发器t22_bi,当我们要向表中的行拔出时,触发器就会被激活,实行将s1列的值改成55的举措。
  INSERTontablewithatrigger利用触发器实行拔出举措

mysql>INSERTINTOt22VALUES(1)//
  让我们看假如向表t2中拔出一行数据触发器对应的表会怎样?
  这里的拔出的举措是很罕见的,我们不必要触发器的权限来实行它。乃至不必要晓得是不是有触发器联系关系。

mysql>SELECT@x,t22.*FROMt22//
+------------------------+------+
|@x|s1|
+------------------------+------+
|Triggerwasactivated!|55|
+------------------------+------+
1rowinset(0.00sec)
  人人能够看到INSERT举措以后的了局,和我们预期的一样,x标志被修改了,同时这里拔出的数据不是我们入手下手输出的拔出数据,而是触发器本人的数据。
Exampleofa"check"constraint
"check"完全性束缚例子
  Whatsa"check"constraint甚么是"check"束缚
  在尺度的SQL言语中,我们能够在(CREATETABLE)创立表的过程当中利用"CHECK(condition)",
比方:

CREATETABLEt25
(s1INT,s2CHAR(5),PRIMARYKEY(s1),
CHECK(LEFT(s2,1)=A))
ENGINE=INNODB;
  这里CHECK的意义是"当s2列的最右边的字符不是A时,insert和update语句城市不法",MySQL的视图不撑持CHECK,我团体是很但愿它能撑持的。但假如你很必要在表中利用如许的功效,我倡议人人利用触发器来完成。

CREATETABLEt25
(s1INT,s2CHAR(5),
PRIMARYKEY(s1))
ENGINE=INNODB//
CREATETRIGGERt25_bi
BEFOREINSERTONt25
FOREACHROW
IFLEFT(NEW.s2,1)ATHENSETNEW.s1=0;ENDIF;//
CREATETRIGGERt25_bu
BEFOREUPDATEONt25
FOREACHROW
IFLEFT(NEW.s2,1)ATHENSETNEW.s1=0;ENDIF;//
  我只必要利用BEFOREINSERT和BEFOREUPDATE语句就好了,删除触发器不会对表有影响,同时AFTER的触发器也不克不及修正NEW的历程变量(transitionvariables)。为了激活触发器,我实行了向表中的行拔出s1=0的数据,以后只需实行切合LEFT(s2,1)A前提的举措城市失利:

INSERTINTOt25VALUES(0,a)/*primingthepump*///
INSERTINTOt25VALUES(5,b)/*getserror23000*///
DontBelieveTheOldMySQLManual
该丢弃旧的MySQL的手册了
  我在这里告诫人人不要信任已往的MySQL手册中所说的了。我们已往失落了关于触发器的毛病的语句,可是仍然有良多旧版本的手册在网上,举个例子,这是一个德国的Url上的:

  http://dev.mysql.com/doc/mysql/de/ANSI_diff_Triggers.html.
  这个手册上说触发器就是存储历程,忘记吧,你也已瞥见了,触发器就是触发器,而存储历程仍是存储历程。
  手册上还说触发器能够从其他表下去删除,大概是当你删除一个事件的时分引发,不管他说的是甚么意义,忘记吧,MySQL不会往完成这些的。
  最初关于说利用触发器会对查询速率发生影响的说法也是错的,触发器不会对查询发生任何影响。
  Bugs
  (欠好的器材就不翻译了)
  OnDecember142004,Ididan"AdvancedSearch"inhttp://bugs.mysql.comfortriggeror
  triggers,Ifoundthattherewere17activebugsasofthatdate.Ofcoursetheymightdisappear
  beforeyoureadthis,butjustincasetheyhavent,Illmentiontheimportantones.Iftheyrestill
  there,youllhavetoworkaroundthemwhenyouretryingtriggers.

  Bug#5859DROPTABLEdoesnotdroptriggers.
  (删除表的时分没有主动删除触发器)
  Whenyoudropatable,droppingthetablestriggersshouldbeautomatic.

  Bug#5892Triggershavethewrongnamespace.
  (触发器的定名空间有错,你必需在后面加上表的名字才干删除触发器,上面是例子)
  Youhavetosay"DROPTRIGGER<tablename>.<triggername>".
  Thecorrectwayis"DROPTRIGGER<triggername>".

  Bug#5894Triggerswithalteredtablescausecorruptdatabases.
  (触发器对表的改动大概会形成数据库数据被损坏)
  Donotalteratablethathasatriggeronit,untilyouknowthisisfixed.

Conclusion最初
  到了书的最初,我以为不必要给人人温习大概是重温一下了,由于信任人人能够很轻松的记着下面所说的。
对免费版的用户也具有充足的支持服务。在dev.mysql.com上,一个大型的MySQL学习教程强大社区用户和开发者可以讨论所有关于MySQL的事情。这个站点拥有博客、指南、视频、技术交流会、白皮书和论坛等方式的交流。
飘灵儿 该用户已被删除
沙发
发表于 2015-1-18 18:14:43 | 只看该作者
发几份SQL课件,以飨阅者
蒙在股里 该用户已被删除
板凳
发表于 2015-1-27 15:42:07 | 只看该作者
varchar(max)\\\\nvarchar(max)类型的引入大大的提高了编程的效率,可以使用字符串函数对CLOB类型进行操作,这是一个亮点。
山那边是海 该用户已被删除
地板
发表于 2015-2-5 13:13:52 | 只看该作者
其实可以做一下类比,Oracle等数据库产品老早就支持了java编程,而且提供了java池参数作为用户配置接口。但是现在有哪些系统大批使用了java存储过程?!连Oracle自己的应用都不用为什么?!
再现理想 该用户已被删除
5#
发表于 2015-2-11 23:58:26 | 只看该作者
很多书籍啊,不过个人认为看书太慢,还不如自己学。多做实际的东西,就会遇到很多问题,网上搜下解决问题。不断重复这个过程,在配合sql的F1功能。
精灵巫婆 该用户已被删除
6#
发表于 2015-3-2 20:52:29 | 只看该作者
连做梦都在想页面结构是怎么样的,绝非虚言
活着的死人 该用户已被删除
7#
 楼主| 发表于 2015-3-11 06:26:01 | 只看该作者
多走走一此相关论坛,多看一些实例开发,多交流0经验,没什么的,我也是刚学没多久!加油
海妖 该用户已被删除
8#
发表于 2015-3-17 22:32:57 | 只看该作者
分区表效率问题肯定是大家关心的问题。在我的试验中,如果按照分区字段进行的查询(过滤)效率会高于未分区表的相同语句。但是如果按照非分区字段进行查询,效率会低于未分区表的相同语句。
小妖女 该用户已被删除
9#
发表于 2015-3-25 04:53:33 | 只看该作者
连做梦都在想页面结构是怎么样的,绝非虚言
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|Archiver|手机版|仓酷云 鄂ICP备14007578号-2

GMT+8, 2024-5-2 23:13

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表