数据库的触发器
1.触发器
触发器是MySQL响应以下任意语句而自动执行的一条MySQL语句(或位于BEGIN和END语句之间的一组语句):
DELETE,INSERT,UPDATE
我们可以监视某表的变化,当发生某种变化时,触发某个操作。
能监视:增,删,改
触发操作:增,删,改
2.触发器应用场景:
1.当向一张表中添加或删除记录时,需要在相关表中进行同步操作。比如,当一个订单产生时,订单所购的商品的库存量相应减少。
2.当表上某列数据的值与其他表中的数据有联系时。比如,当某客户进行欠款消费,可以在生成订单时通过设计触发器判断该客户的累计欠款是否超出了最大限度。
3.当需要对某张表进行跟踪时。比如,当有新订单产生时,需要及时通知相关人员进行处理,此时可以在订单表上设计添加触发器加以实现
3.创建和删除触发器
创建触发器:
>create trigger trig after insert on orders for each row select new.orser_name;
>insert语句,触发语句,返回一个值
删除触发器
>drop trigger trig;
数据库的存储引擎
1.存储引擎概念
1)mysql中的数据用各种不同的技术存储在文件系统中,每一种技术都使用不同的存储机制、索引技巧,锁定水平并最终提供不同的功能和能力,这些不同的技术以及配套的功能在mysql中称为存储引擎。
2)存储引擎就是mysql将数据存储在文件系统中的存储方式或者存储格式。
3)目前mysql常用的两种存储引擎:MyiSAM,InnoDB。
常见的存储引擎:show engines;
myisam, aria, innodb, mrg_myisam, csv, blackhole, memory, performance_schema, archive, federated
4)mysql存储引擎是mysql数据库服务器中的组件,负责为数据库执行实际的数据I/O操作,使用特殊存储引擎的主要优点之一在于仅需提供特殊应用所需的特性,数据库中的系统开销较小,具有更有效和更高效的数据库性能。
5)mysql系统中,存储引擎处于文件系统之上,在数据保存到数据文件之前会传输到存储引擎,之后按照各个存储引擎的存储格式进行存储。
2.存储引擎特点对比
![](https://images2018.cnblogs.com/blog/1250974/201803/1250974-20180302115553155-916706959.png)
3.MyISAM
MyISAM是MySQL的默认存储引擎,MyISAM不支持事务、也不支持外键,但其访问速度快,对事务完整性没有要求。
1)MySAM概述
1》MyISAM存储引擎是mysql关系数据库系统5.5版本之前默认的存储引擎,前身是ISAM。
2》ISAM是一个定义明确且经历时间考验的数据表格管理方法,在设计之时就考虑到数据库被查询的次数要远大于更新的次数。
3》ISAM的特点:ISAM执行读取操作的速度很快,而且占用不大量的内存和存储资源,它不支持事务处理,不能够容错。
4》MyISAM管理非事务表,是ISAM的扩展格式,提供ISAM里所没有的索引和字段管理的大量功能。
5》MyISAM使用一种表格锁定的机制,以优化多个并发的读写操作。MyISAM提供高速存储和检索,以及全文搜索能力,受到web开发的青睐。
6》要指定索引和数据文件的路径时,需要在创建表时通过'data directory'和'index dircetory'语句来指定,即它们可以放置在不同的路径下,当然要给出其绝对路径且还要有相应的权限。
7》造成myisam类型表损坏的原因有多种,且损坏后表就不能再被访问了,会提示错误的结束或要求修正或异常重启。解决的方法有:使用'check table'来检查myisam表,'repair table'可用来修复一个受损的myisam表。
8》在myisam表中,自增列可以是组合索引的其它列,当插入记录后,自增列是按组合索引的前几列进行排序后递增的。
2)MyISAM的特点
1》不支持事务
2》锁粒度:表级锁定形式,数据在更新时锁定整个表
3》数据库在读写过程中相互阻塞,会在数据写入的过程中阻塞用户的读取,也会在数据读取的过程中阻塞用户的数据写入。
4》可以通过key_buffer_size来设置缓存索引,提高访问性能,减少磁盘I/O的压力,但缓存只会缓存索引文件,不会缓存数据。
5》采用MyISAM存储引擎数据单独写入或读取,速度过程较快而且占用资源相对较少。
6》MyISAM存储引擎不支持外键约束,使用非聚集索引,支持全文索引(fulltext index)、压缩、空间函数(GIS)
7》崩溃无法保证表完全恢复
8》每个MyISAM在磁盘上存储成三个文件,每个文件的名字以表的名字开始,扩展名指出文件类型。
tbl_name.frm文件存储表定义,表格式文件;
.MYD文件存储数据(MYData),数据文件;
.MYI文件存储索引文件(MYIndex),索引文件;
9》行格式:
{default|dynamic|fixed|compressed|redundant|compact}
3)MyISAM的表还支持3中不同的存储格式:
静态表
动态表
压缩表
1》静态表是默认的存储格式,静态表中的字段都是非变长的字段。
优点是:存储非常迅速,容易缓存,出现故障容易恢复;
缺点是:占用的空间通常比动态表多。
(注意: 在存储时,列的宽度不足时,用空格补足,在返回给应用时并不会将这些空格也给应用;同理当字段后本来有空格时,数据库也会自动处理掉它,但字段前的空格将会保留)
2》动态表的字段是变长的,优点是:占用的空间相对较少,但是频繁地更新删除记录会产生碎片,需要定期改善性能(optimize table或myisamchk -r命令),并且出现故障的时候恢复相对比较困难。
3》压缩表占用磁盘空间小,每个记录是被单独压缩的,所以只有非常小的访问开支且为只读。
4)MyISAM使用的场景
1》公式业务不需要事务支持
2》一般单方读取数据比较多的业务,或单方面写入数据比较多的业务,如图片信息数据库等MyISAM存储引擎数据读写都比较频繁的场景不适合。
3》对数据业务一致性要求不是非常高的业务
4》使用读写并发访问相对较低的业务
5》数据修改相对较少的业务
6》服务器硬件资源相对比较差
7》只读或读多写少的场景、较小的表(以保证崩溃后恢复的时间较短)
8》如果你的应用是不需要事务,处理的只是基本的CRUD操作,那么MyISAM是不二选择。
4.InnoDB
InnoDB提供事务安全表,其他存储引擎都是非事务安全表。
InnoDB存储引擎提供了具有提交、回滚和崩溃恢复能力的事务安全。但是比起MyISAM存储引擎,InnoDB写的处理效率差一些并且会占用更多的磁盘空间以保留数据和索引。
支持外键存储引擎的只有InnoDB,在创建外键的时候,要求附表必须有对应的索引,子表在创建外键的时候也会自动创建对应的索引。
1)InnoDB的特点
1》支持事务,支持4个事务隔离级别
2》行级锁定,但是全表扫描仍然会是表级锁定
3》读写阻塞与事务隔离级别相关
4》具有非常高效的缓存特性,能缓存索引,也能缓存数据
5》表与主键以簇的方式存储
6》支持分区,表空间,类是oracle数据库
7》支持外键约束,5.5以前不支持全文索引,5.5版本后支持全文索引
8》对硬件资源要求比较高
2)InnoDB存储方式为两种:
使用共享表空间存储
使用多表空间存储
1》使用共享表空间存储,这种方式创建的表的结构保存在'.frm'文件中,数据和索引保存在innodb_data_home_dir和innodb_data_file_path定义的表空间中,可以是多个文件。
2》使用多表空间存储,这种方式创建的表结构仍然保存在'.frm'文件中,但数据和索引单独保存中'.ibd'文件中。如果是分区表,则每个分区对应单独的'.ibd'文件,文件名是“表名+分区名”,可以在创建分区时指定每个分区的数据文件位置,以此来将i/o分布在多个磁盘上。要使用多表空间方式,需要设置参数:innodb_file_per_table,并重启服务生效,新建表将新的方式来创建,已有的表仍会使用共享表空间方式存储。如果将已有的多表空间方式改回为共享表方式,则新建表会在共享表空间中创建,但已经有的多表空间依然保持原有的访问方式。所以表空间参数生效后,只对新建的表有效。
3》多表空间方式的数据文件没有大小限制,无需初始其大小,也不需要设置文件最大限制、扩展大小等参数。对于多表空间表,可以比较方便地进行单表备份和恢复,但直接复制'.ibd'文件是不行的,因为没有提供其数据字典信息,直接复制'.ibd'与'.frm'文件恢复时是不能被正确识别的,要通过下面指令来操作:
alter table tbl_x discard tablespace;
alter table tbl_x import tablespace;
即可将备份恢复到数据库中,但这种的单表备份,只能恢复到原表所在的数据库中,而不能恢复到其它库中,当然这需要使用'mysqldump'或'mysqlimport'工具来实现。
注意:即使在多表空间模式下,共享表空间是必须的,因为innodb将内部数据词典和未完成日志存放于此。
3)补充知识点
1)当对auto_increment列插入空、'0'、'null'时,它都将自动转换为合适且正确值。
2)当使用'last_insert_id()'查询当前线程最后插入记录使用值,若一次插入了多条记录,则它返回的是第一条记录所使用的自增值。
3)对于innodb表,自动增长列必须是索引,如果是组合索引,也必须是其的第一列,这个与myisam是有区别的。
4)InnoDB被设计成适用于高并发读写的情况.使用MVCC(Multi-Version Concurrency Control)以及行级锁来提供遵从ACID的事务支持。InnoDB支持外键参照完整性,具备故障恢复能力。另外 InnoDB的性能其实还是不错的,特别是在处理大数据量的情况下。
5)InnoDB的CPU效率是其他基于磁盘的关系数据库存储引擎所不能比的。不过InnoDB的备份恢复要麻烦一点,除非你使用了4.1以后版本提供的Mulit-tablespace支持,因为InnoDB和MyISAM不同,它的数据文件并不是独立对应于每张表的,而是使用的共享表空间,简单的拷贝覆盖方法对他不适用,必须在停掉MYSQL后对进行数据恢复。使用Per-Table Tablespacesd,使其每张表对应一个独立的表空间文件,则情况要简单很多。
6)在指定外鍵约束时,可以指定在删除、更新父表时,对子表进行相应操作,包括:restrict、cascade、set null、no action。
其中restrict与no action相同,即限制在子表有关联记录的情况下父表不能更新;
cascade表示父表在更新或删除时,更新或删除子表对应的记录;
set null则表示父表在更新或删除时,更新或删除子表对应的字段被set null。
所以选择后两种方式要谨慎,可能会因此错误的操作导致数据丢失。当某表被其它表创建了外键参照,那么该表的对应索引或主键禁止被删除。
7)在导入多个表的数据时,如果需要忽略表之前的导入顺序,可以暂时关闭外键的检查;同理,在执行load data 和 alter table操作的时候,可以通过暂时关闭外键约束来加快处理速度,指令是:"set foreign_key_checks=0;",在处理完成后,通过"set foreign_key_checks=1;"来复原。
4)innodb:
percona-xtradb, supports transactions, row-level locking, and foreign keys
数据存储于“表空间(table space)"中:
(1) 所有数据库中的所有类型为innodb的表的数据和索引存储于同一个表空间中;
表空间文件:datadir定义的目录中
文件:ibdata1, ibdata2, ...
(2) innodb_file_per_table=on,意味着每表使用单独的表空间文件;
每表的数据文件(数据和索引,存储于数据库目录)存储于自己专用的表空间文件中,并存储于数据库目录下: tbl_name.ibd
表结构的定义:在数据库目录,tbl_name.frm
事务型存储引擎,适合对事务要求较高的场景中;但较适用于处理大量短期事务;
基于mvcc(mutli version concurrency control)支持高并发;支持四个隔离级别,默认级别为repeatable-read;间隙锁以防止幻读;
使用聚集索引(主键索引);
支持”自适应hash索引“;
锁粒度:行级锁;间隙锁;
总结:
数据存储:表空间;
并发:mvcc,间隙锁,行级锁;
索引:聚集索引、辅助索引;
性能:预读操作、内存数据缓冲、内存索引缓存、自适应hash索引、插入操作缓存区;
备份:支持热备;
5)innodb存储引擎相关的参数:
innodb_buffer_pool_size:
索引、数据、插入数据时的缓冲区
专用服务器70-80%;
如果数据集本身较小,可根据数据变化幅度及规划的时长也设定合理值,比预估的目标值略大;
innodb_buffer_pool_instances:
buffer_pool的区段(实例)数量;
事务日志:
innodb_log_files_in_group:一组的日志文件数量,至少2个;
innodb_log_file_size:日志文件大小,默认为5m;建议调大此值;
innodb_flush_logs_at_trx_commit:
0:log buffer(内存)每秒一次同步到log file中,且同时会进行log file到data file的同步操作;
1:每次提交时,log buffer同步到log file,同时进行log file到data file的同步操作;
2:每次提交时,log buffer同步到log file,但不会同时进行log file到data file的同步操作;
建议:关闭autocommit,而后将此值设置为1或2;
innodb_file_per_table:innodb的诸多高级特性都依赖于此参数;
innodb_read_io_threads:
innodb_write_io_threads
文件读写的io线程数;可根据并发量和cpu核心数适当调整;
innodb_open_files:innodb可打开的文件数量上限;
innodb_flush_method:
innodb_thread_concurrency=
skip_name_resolve:
max_connections:
5)InnoDB使用的场景
1》业务需要事务的支持
2》行级锁定对高并发有很好的适应能力,但需要确保查询是通过索引来完成
3》业务数据更新较为频繁的场景,如论坛
4》业务数据一致性要求较高,如银行业务
5》硬件设备内存较大,利用InnoDB较好的缓存能力来提高内存利用率,减少磁盘I/O的压力。
5.MEMORY
1)MEMORY存储引擎使用存在内存中的内容来创建表。每个MEMORY表只实际对应一个磁盘文件。MEMORY类型的表访问非常得快,因为它的数据是放在内存中的,并且默认使用HASH索引。但是一旦服务关闭,表中的数据就会丢失掉。其次它有空间大小的限制。
2)MEMORY类型的存储引擎主要用于那些内容变化不频繁的代码表,或者作为统计操作的中间结果表,便于高效地对中间结果进行分析并得到最终的统计结果。对MEMORY存储引擎的表进行更新操作要谨慎,因为数据并没有实际写入到磁盘中,所以一定要对下次重新启动服务后如何获得这些修改后的数据有所考虑。 此类表实际仅对应一个磁盘文件:.frm,默认使用hash索引。
3)每个memory表所能放置的数据量受到max_heap_table_size系统变量约束,初始值为16MB,可以按需加大,另外在其定义时,可以通过max_rows来指定表的最大行数。服务器需要充足的内存来维持这些表,当不需要这些表及内容时,清空(delete from 或 truncate)它们可以释放内存。当数据量过大时,就会报出ERROR 1114 (HY000): The table 'arts' is full,而导致建表失败。此种类型表有许多自身不足,从而限制了其用途。大小限制、字段类型限制、无持久性。查询速度快,可用其做一些中间结果暂存表之用。
6.MERGE
1)MERGE用于将一系列等同的MyISAM表以逻辑方式组合在一起,并作为一个对象引用它。
2)MERGE表的优点在于可以突破对单个MyISAM表大小的限制,通过将不同的表分布在多个磁盘上,可以有效的改善MERGE表的访问效率。
3)MERGE存储引擎是一组MyISAM表的组合,这些MyISAM表必须结构完全相同。MERGE表本身没有数据,对MERGE类型的表进行查询、更新、删除的操作,就是对内部的MyISAM表进行的。
4)对此类表的插入操作,是通过insert_method子句定义的表,可以有3个不同值:first:作用在第一个表上;last:作用在最后一个表上;不定义或定义为'no',不能对这个merge表进行插入操作。当对其进行drop时,只是删除了merge的定义,而对内部表内容没有影响。
5)merge表在磁盘上有两个相关文件,一个是'.frm'文件存储表定义,另一个'.mrg'文件包含了组合表的信息,由哪些表组成、插入数据时的依据规则。可以直接通过编辑'.mrg'文件来修改其内容,后通过'flush tables'来刷新生效。
6)merge表并不能智能地将记录写到对应的表中,而分区是支持此类逻缉的,它们在使用上是透明的。需要注意的是,分区表不是存储引擎。
5.选择存储引擎的依据
1》需要考虑每个存储引擎提供了那些不同的核心功能以及应用场景
2》支持的字段和数据类型,所有引擎都支持通用的数据类型,但不是所有引擎都支持其他的字段类型,如二进制对象。
3》锁定类型:不同的存储引擎支持不同级别的锁定
表锁定:MyISAM,MEMORY
行锁定:InnoDB
页锁定:BDB
4》索引的支持
建立索引在搜索和恢复数据库中的数据的时候能显著提高性能,不同的存储引擎提供不同的制作索引的技术,有些存储引擎根本不支持索引。
5》事务处理的支持
事务处理功能通过提供在想表中更新和插入信息期间的可靠性,可根据企业业务是否要支持事务选择存储引擎。
6》据应用特点选择合适的存储引擎,对于复杂的应用系统可以根据实际情况选择多种存储引擎进行组合。
7》常用存储引擎的适用环境:
1、MyISAM:默认的MySQL插件式存储引擎,它是在Web、数据仓储和其他应用环境下最常使用的存储引擎之一
2、InnoDB:用于事务处理应用程序,具有众多特性,包括ACID事务支持
3、Memory:将所有数据保存在RAM中,在需要快速查找引用和其他类似数据的环境下,可提供极快的访问
4、Merge:允许MySQL DBA或开发人员将一系列等同的MyISAM表以逻辑方式组合在一起,并作为1个对象引用它们。对于诸如数据仓储等VLDB环境十分适合。
6.配置适合的存储引擎
1)查看数据库可配置的存储引擎
登录mysql,使用show engines查看系统所支持的引擎
show engines;
2)查看表正在使用的存储引擎
1》查看当前mysql的默认引擎
show engines;
2》查看表使用的存储引擎
1>show table status from 库名 where name='表名';
2>show create table 表名;
3》示例
查看此数据库中所有表的存储引擎
show table status \G
查看此数据库中某个表的存储引擎
show table status like 'stu%' \G
查看此数据库中存储引擎为innodb的表
show table status where engine='innodb' \G
可以查看到这个表的存储引擎
show table status like 'students2'\G
3)配置存储引擎为所选择的类型
1>alter table 表名 engine=引擎;
2>修改my.cnf的default-storage-engine
vim /etc/my.cnf
[mysqld]
default-storage-engine=InnoDB
service nginx restart
3>create table 建立表时使用engine=引擎
create table 表名 engine=引擎;
创建表并指定存储引擎
create table students2(id int,name char(10)) engine=myisam;
4>mysql_convert_table_format --uroot --password=密码 --sock=/文件路径/mysql.sock --engine=引擎 库名 表名;
注意:通过这个方法从InnoDB改为MyISAM没有问题,但反过来就不行。
7.其他
其它的存储引擎:
csv:将csv文件(以逗号分隔字段的文本文件)作为mysql表文件;
mrg_myisam:将多个myisam表合并成的虚拟表;
blackhole:类似于/dev/null,不真正存储数据;
memory:内存存储引擎,支持hash索引,表级锁,常用于临时表;
federated: 用于访问其它远程mysql服务器上表的存储引擎接口;
mariadb额外支持很多种存储引擎:
oqgraph、sphinxse、tokudb、cassandra、connect、squence、...
搜索引擎:
lucene, sphinx
lucene:solr, elasticsearch
数据库存储过程
1.存储过程
1)我们常用的操作数据库语言SQL语句在执行的时候需要要先编译,然后执行。而存储过程(Stored Procedure)是一组为了完成特定功能的SQL语句集,经编译后存储在数据库中,用户通过指定存储过程的名字并给定参数(如果该存储过程带有参数)来调用执行它。
2)一个存储过程是一个可编程的函数,它在数据库中创建并保存。它可以有SQL语句和一些特殊的控制结构组成。当希望在不同的应用程序或平台上执行相同的函数,或者封装特定功能时,存储过程是非常有用的。数据库中的存储过程可以看做是对编程中面向对象方法的模拟。它允许控制数据的访问方式。
3)存储过程是 SQL 语句和控制语句的预编译集合,以一个名称存储并作为一个单元处理。
4)存储过程是由过程化 SQL 语句书写的过程,这个过程经编译和优化后存储在数据库服务器中,因此称它为存储过程,使用时只要调用即可。
5)大多数SQL语句都是针对一个或多个表的单条语句。并非所有的操作都怎么简单。经常会有一个完整的操作需要多条才能完成。而存储过程简单来说,就是为以后的使用而保存的一条或多条MySQL语句的集合。可将其视为批文件。虽然他们的作用不仅限于批处理。
2.存储过程的优点
1)存储过程增强了SQL语言的功能和灵活性。
存储过程可以用流控制语句编写,有很强的灵活性,可以完成复杂的判断和较复杂的运算。
2)存储过程允许标准组件是编程。
存储过程被创建后,可以在程序中被多次调用,而不必重新编写该存储过程的SQL语句。而且数据库专业人员可以随时对存储过程进行修改,对应用程序源代码毫无影响。
3)存储过程能实现较快的执行速度。
如果某一操作包含大量的Transaction-SQL代码或分别被多次执行,那么存储过程要比批处理的执行速度快很多。因为存储过程是预编译的。在首次运行一个存储过程时查询,优化器对其进行分析优化,并且给出最终被存储在系统表中的执行计划。而批处理的Transaction-SQL语句在每次运行时都要进行编译和优化,速度相对要慢一些。
4)存储过程能过减少网络流量。
针对同一个数据库对象的操作(如查询、修改),如果这一操作所涉及的Transaction-SQL语句被组织程存储过程,那么当在客户计算机上调用该存储过程时,网络中传送的只是该调用语句,从而大大增加了网络流量并降低了网络负载。
5)存储过程可被作为一种安全机制来充分利用。
系统管理员通过执行某一存储过程的权限进行限制,能够实现对相应的数据的访问权限的限制,避免了非授权用户对数据的访问,保证了数据的安全。
3.存储过程的创建
help create procedure
1)create
[definer = { user | current_user }]
procedure sp_name ([proc_parameter[,...]])
[characteristic ...] routine_body
2)create
[definer = { user | current_user }]
function sp_name ([func_parameter[,...]])
returns type
[characteristic ...] routine_body
3)参数
proc_parameter:
[ in | out | inout ] param_name type
func_parameter:
param_name type
type:
any valid mysql data type
characteristic:
comment 'string' | language sql | [not] deterministic | { contains sql | no sql | reads sql data | modifies sql data } | sql security { definer | invoker }
routine_body:
valid sql routine statement
4)官方示例
mysql> delimiter //
mysql> CREATE PROCEDURE simpleproc (OUT param1 INT)
-> BEGIN
-> SELECT COUNT(*) INTO param1 FROM t;
-> END//
mysql> delimiter ;
mysql> CALL simpleproc(@a);
mysql> SELECT @a;
+------+
| @a |
+------+
| 3 |
+------+
mysql> CREATE FUNCTION hello (s CHAR(20))
mysql> RETURNS CHAR(50) DETERMINISTIC
-> RETURN CONCAT('Hello, ',s,'!');
mysql> SELECT hello('world');
+----------------+
| hello('world') |
+----------------+
| Hello, world! |
+----------------+
1》声明分割符
在创建存储过程前,最好进行分隔符的声明。
使用delimiter(定界符),例如:
delimiter //
....(存储过程的创建语句)
delimiter ;
因为MySQL默认以";"为分隔符,如果我们没有声明分割符,那么编译器会把存储过程当成SQL语句进行处理,则存储过程的编译过程会报错,所以要事先用delimiter关键字声明当前段分隔符,这样MySQL才会将";"当做存储过程中的代码,不会执行这些代码,用完了之后要把分隔符还原。当然要注意一点:如果是用MySQL的Administrator管理工具时,可以直接创建,不再需要声明。
2》相关解释
definer:创建者,默认为当前用户
sp_name:过程名,默认为当前数据库中创建
proc_parameter:为过程参数列表
proc_parameter主要有三个参数:in,out,inout。
in:
输入参数,表示该参数的值必须在调用存储过程时指定,在存储过程中修改该参数的值不能被返回,为默认值
out:
输出参数,该值可在存储过程内部被改变,并可返回。
inout:
输入输出参数,调用时指定,并且可被改变和返回。
param_name:参数名,多个参数间用逗号分割。
type:参数的数据类型
characteristic:存储过程的某些特征设定
1)comment’string’:用于对存储过程的描述,其中string为描述内容,comment为关键字。
2)language sql :指明编写这个存储过程的语言为SQL语言。这个选项可以不指定。
3)deterministic:表示存储过程对同样的输入参数产生相同的结果;not deterministic,则表示会产生不确定的结果(默认)。
4)contains sql | no sql | reads sql data | modifies sql data Contains sql表示存储过程包含读或写数据的语句(默认)
5)No sql:表示不包含sql语句
6)Reads sql data:表示存储过程只包含读数据的语句
7)Modifies sql data :表示存储过程只包含写数据的语句
5)sql security:这个特征用来指定存储过程使用创建该存储过程的用户(definer)的许可来执行,还是使用调用者(invoker)的许可来执行。默认是definer。
routine_body:存储过程的主体部分,包含了在过程调用的时候必须执行的sql语句。以begin开始,以end结束,如果存储过程体中只有一条sql语句,可以省略begin-end标志。
3》存储过程的过程体
过程体的开启与结束是使用begin和end进行标识的。在bigin和end之间可以是复合结构,包含声明,循环,控制等语句结构。
存储过程体中可以使用各种sql语句和过程式语句的组合,来封装数据库应用中复杂的业务逻辑和处理规则,以实现数据库应用的灵活编程。
1>使用局部变量
在存储过程体中可以声明局部变量,用来存储存储过程体中临时结果。
使用declare来定义
help declare variable
declare var_name [, var_name] ... type [default value]
使用说明
局部变量只能在存储过程体的begin…end语句块中声明。
局部变量必须在存储过程体的开头处声明。
局部变量的作用范围仅限于声明它的begin..end语句块,其他语句块中的语句不可以使用它。
局部变量不同于用户变量,两者区别:局部变量声明时,在其前面没有使用@符号,并且它只能在begin..end语句块中使用;而用户变量在声明时,会在其名称前面使用@符号,同时已声明的用户变量存在于整个会话之中。
2>set 语句
使用set语句为局部变量赋值
help set
set variable_assignment [, variable_assignment] ...
variable_assignment:
user_var_name = expr | [global | session] system_var_name = expr | [@@global. | @@session. | @@]system_var_name = expr
SET var_name = expr [, var_name = expr] ...
在存储程序中的SET语句是一般SET语句的扩展版本。被参考变量可能是子程序内声明的变量,或者是全局服务器变量。
3>select … into 语句
把选定列的值直接存储到局部变量中。
SELECT col_name[,...] INTO var_name[,...] table_expr
Col_name:用于指定列名
Var_name:用于指定要赋值的变量名
Table_expr:表示select语句中的from字句及后面的语法部分
这个SELECT语法把选定的列直接存储到变量。因此,只有单一的行可以被取回。
4>定义处理程序
事先定义程序执行过程中可能遇到的问题。并且可以在处理程序中定义解决这些问题的办法。这种方式可以提前预测可能出现的问题,并提出解决方法。
使用declare handler来定义
help declare handler
declare handler_action handler
for condition_value [, condition_value] ...
statement
参数:
handler_action:
continue | exit | undo
condition_value:
mysql_error_code | sqlstate [value] sqlstate_value | condition_name | sqlwarning | not found | sqlexception
官方示例:
mysql> CREATE TABLE test.t (s1 INT, PRIMARY KEY (s1));
mysql> delimiter //
mysql> CREATE PROCEDURE handlerdemo ()
-> BEGIN
-> DECLARE CONTINUE HANDLER FOR SQLSTATE '23000' SET @x2 = 1;
-> SET @x = 1;
-> INSERT INTO test.t VALUES (1);
-> SET @x = 2;
-> INSERT INTO test.t VALUES (1);
-> SET @x = 3;
-> END;
-> //
mysql> CALL handlerdemo()//
mysql> SELECT @x//
+------+
| @x |
+------+
| 3 |
+------+
5>流控制语句
(1)条件判断语句
if语句、case语句
1》》if语句
help if
help if statement
if search_condition then statement_list
[elseif search_condition then statement_list] ...
[else statement_list]
end if
Search_condition:条件判断语句
Statement_list:不同条件的执行语句
help if function
if (expr1,expr2,expr3)
If expr1 is TRUE (expr1 <> 0 and expr1 <> NULL) then IF() returns
expr2; otherwise it returns expr3. IF() returns a numeric or string
value, depending on the context in which it is used.
2》》case语句
help case
help case operator
case value when [compare_value]
then result [when [compare_value] then result ...] [else result] end
case when [condition]
then result [when [condition] then result ...] [else result] end
help case statement
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
官方示例:
delimiter |
create procedure p()
begin
declare v int default 1;
case v
when 2 then select v;
when 3 then select 0;
else
begin
end;
end case;
end;
|
(6)循环语句
while语句、repeat语句、loop语句
1》》while语句
help while
[begin_label:] while search_condition do statement_list
end while [end_label]
判断条件search_condition是否为真,若为真,则执行statement_list中的语句,然后再进行判断,如若仍然为真则继续循环,直至条件判断不为真时循环结束。
官方示例:
create procedure dowhile()
begin
declare v1 int default 5;
while v1 > 0 do
...
set v1 = v1 - 1;
end while;
end;
2》》repeat语句
help repeat
[begin_label:] repeat statement_list
until search_condition
end repeat [end_label]
Repeat语句首先执行statement_list中的语句,然后判断条件search_condition是否为真,倘若为真,则结束循环,若不为真,继续循环。
官方示例:
mysql> delimiter //
mysql> CREATE PROCEDURE dorepeat(p1 INT)
-> BEGIN
-> SET @x = 0;
-> REPEAT
-> SET @x = @x + 1;
-> UNTIL @x > p1 END REPEAT;
-> END
-> //
mysql> CALL dorepeat(1000)//
mysql> SELECT @x//
+------+
| @x |
+------+
| 1001 |
+------+
3》》loop语句
help loop
[begin_label:] loop statement_list
end loop [end_label]
官方示例:
create procedure doiterate(p1 int)
begin
label1: loop
set p1 = p1 + 1;
if p1 < 10 then
iterate label1;
end if;
leave label1;
end loop label1;
set @x = p1;
end;
4.存储过程的调用、查询、修改和删除
1)调用
使用call来调用
help call
call sp_name([parameter[,...]])
call sp_name[()]
Sp_name:被调用存储过程的名称
Parameter:指定调用存储过程所要使用的参数。
2)查询
使用show和select来查询
help show
show create procedure proc_name
show procedure code proc_name
show procedure status [like_or_where]
help select
select
...
[PROCEDURE procedure_name(argument_list)]
...
3)修改
使用alter来进行修改
help alter procedure
alter procedure proc_name [characteristic ...]
characteristic:
comment 'string' | language sql | { contains sql | no sql | reads sql data | modifies sql data } | sql security { definer | invoker }
只能修改存储过程的特征,如果要修改存储过程的内容,可以先删除该存储过程,然后再重新创建。
4)删除
使用drop来进行删除
help drop procedure
drop {procedure | function} [if exists] sp_name