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

MySQL高阶之事务、存储结构、索引、触发器

2017-09-02 16:51 731 查看
差不多mysql的一些知识也学完了,数据库除了基本的增删改查操作外,要开始进入高阶部分了,那么mysql的高阶部分有哪些呢?虽然这些内容中有些平时用的很少,但是站在大数据环境下,有些内容确实显得格外重要,接下来,让我们一起来了解下吧!

事务

定义

事务就是被绑定在一起作为一个逻辑工作单元的SQL语句分组,要么执行,要么不执行,就可以使用事务要将有组语句作为事务考虑,就需要通过 ACID 测试,即原子性一致性隔离性和持久性。就拿我们平时很常见的操作,比如转账就是一个事务。

管理事务

BEGIN TRANSACTION:开始事务

COMMIT TRANSACTION:提交事务

ROLLBACK TRANSACTION:回滚事务

事务的作用范围

事务从BEGIN开始,到COMMIT或ROLLBACK结束,中间的所有的SQL语句构成一个完整的逻辑单元,统一成功或失败。

存储结构

定义

存储过程是一个预编译的SQL语句,优点是允许模块化的设计,就是说只需创建一次,以后在该程序中就可以调用多次。

存储过程用来执行管理任务或应用复杂的业务。

存储过程作为一个方法,也有方法名、参数和返回值。

优点

执行速度更快

允许模块化程序设计

提高系统安全性

减少网络流通量

语法

CREATE  PROCEDURE  存储过程名
([过程参数[,...]])
[特性 ...]
BEGIN
DECLARE 变量名 数据类型 [DEFAULT 默认值]
过程体
END


实例

无返回值的存储过程

例如:计算退休员工的平均工龄

DROP PROCEDURE IF EXISTS proc_retireemployee;
CREATE PROCEDURE proc_retireemployee()
BEGIN
DECLARE avgretireage FLOAT DEFAULT 0;
SET @avgretireage = (SELECT AVG(workyear) FROM retireemployee);
SELECT ‘平均工龄:’ + @avgretireage AS '平均工龄';
SELECT * FROM retireemployee WHERE workyear>45;
END


调用方式

CALL 存储过程名[参数]


有传入值和返回值的存储过程

例如:给员工表的删除操作添加审查功能,工龄够45年的允许删除,不够的不允许删除,并把删除结果返回。

DROP PROCEDURE IF EXISTS proc_deleteemployeeplus;
/* 定义一个传入参数和一个传出参数 */
CREATE PROCEDURE proc_deleteemployeeplus(IN in_id VARCHAR(50),OUT out_flag VARCHAR(1))
BEGIN
DECLARE de_username VARCHAR(50) DEFAULT '';
DECLARE de_begood VARCHAR(100) DEFAULT '';
DECLARE de_entrytime DATE;
DECLARE de_workyear INT DEFAULT 0;
SELECT @de_username:=username,@de_begood:=begood, @de_entrytime:=entrytime FROM employee WHERE id = in_id;
SET @de_workyear = YEAR(NOW())-YEAR(@de_entrytime);
IF @workyear >= 45 THEN
INSERT INTO retireemployee(id,username,begood,entrytime,retiretime,workyear)
VALUES(UUID(),@de_username,@de_begood,@de_entrytime,NOW(),YEAR(NOW())-YEAR(@de_entrytime));
DELETE FROM employee WHERE id = in_id;
SET out_flag = '1';
ELSE
SET out_flag = '0';
END IF;
END


调用方式:

CALL proc_deleteemployeeplus('531cc97b-8641-11e7-a265-d8cb8a7ce2c9',@out_flag);
SELECT @out_flag;


下面介绍两种特殊的存储结构————————————————

索引

定义

所谓索引,从官方角度来讲,索引实质就是对于关系型数据库而言,在创建数据库上,是一种对一列或者多列的值进行单独地排序的存储结构,也是一种特殊的查询表。

简单来讲,比如,记忆似水流年,曾经我们使用过新华词典,每次使用查询字时,词典的前部分都会有按照拼音、部首等其他查询方式来使你快速查询你所想要查询的字,那么这些拼音、部首等就是我们所讲的索引。

语法

CREATE INDEX 索引名 ON table(列名(长度))


例如:
CREATE INDEX index_book_title ON book(title(10))


在这里要说明一点,对于char和varchar类型的列,这一部分通常是指前缀的部分。长度10就是指使用列值中的前10个字符来创建索引,因为多数名称的前10个字符通常不同,所以使用前10个字符就够了。

另外,使用列的一部分创建索引可以使索引文件大大减小,从而节省了大量的磁盘空间,有可能提高INSERT操作的速度。

因此使用小结如下:

- 对于CHARVARCHAR类型的列,前10个就够了

- 如果是BLOBTEXT类型,必须指定实际长度

类型

普通索引:Normal,最基本的索引,它对列没有任何要求。

唯一索引:索引列的值必须唯一,如果是组合索引,则列值的组合必须唯一,这和主键很像,但主键不允许为空,唯一索引允许列值为空。

CREATE UNIQUE INDEX 索引名 ON table(列名(长度))


例如:
CREATE UNIQUE INDEX index_book_title
ON book(title(10))


全文索引:用于对一个文本的所有内容进行检索,所以它主要作用于CHAR、VARCHAR或TEXT类型的列;全文检索仅可作用于MyISAM表。

CREATE FULLTEXT INDEX 索引名 ON table(列名)


例如:
CREATE FULLTEXT INDEX index_book_category
ON book(category)


注意事项

不要在所有的表上都建索引,只在数据量比较大的表上建立索引,小表没有建立索引的必要

不要在所有的列上建立索引,我们应该只在常常检索的列上建立索引,这些列往往是你where子句后最常出现的字段。

选择合适的索引类型,而不是简单的使用默认索引。

触发器

定义

所谓触发器,触发器是一种特殊的存储过程,主要是通过事件来触发而被执行的。它可以强化约束,来维护数据的完整性和一致性,可以跟踪数据库内的操作从而不允许未经许可的更新和变化。

应用场景

触发器通常用于强制业务。

触发器是一种高级约束,是比主键和外键更为复杂的约束。

语法

CREATE TRIGGER 触发器名称
{ BEFORE | AFTER }
{ INSERT | UPDATE | DELETE }
ON 表名
FOR EACH ROW
BEGIN
触发器业务代码
END;

说明:
1.BEFORE | AFTER: 触发时间,执行前出发还是执行后触发
2.INSERT | UPDATE | DELETE:监听事件,也就是触发类型
3.表名:监听地点,也就是作用于哪个表
4. FOR EACH ROW:行级触发器,除了行级,还有列级和语句级
5. 触发器业务代码:触发事件,也就是要执行的SQL语句


类型

新增触发器

触发器触发时,系统自动在内存中自动创建了一个叫做NEW的临时表,它只读,不允许修改,触发器执行完成后自动删除。

NEW表主要有以下作用:

它临时保存了插入后的记录行

可以从NEW表中检查插入的数据是否满足业务需求

例如:

表结构:

-- 创建stu的日志表--
CREATE TABLE stu_log(
id VARCHAR(36) NOT NULL COMMENT '编号',
operationtype VARCHAR(36) NOT NULL COMMENT '操作类型',
operationid VARCHAR(36) NOT NULL COMMENT '操作类型id',
oldvalue VARCHAR (500) DEFAULT NULL COMMENT '操作之前的值',
newvalue VARCHAR (500) DEFAULT NULL COMMENT '操作之后的值',
createtime date NOT NULL COMMENT '操作时间'
) ENGINE = INNODB DEFAULT CHARSET = utf8;


触发器:

CREATE TRIGGER trigger_stu_insert
AFTER INSERT
ON stu
FOR EACH ROW
BEGIN
INSERT INTO stu_log(id,operationtype,operationid,createtime) VALUES(UUID(),'insert',NEW.id,NOW());
END;


删除触发器

触发器触发时,系统自动在内存中自动创建了一个叫做OLD的临时表,它只读,不允许修改,触发器执行完成后自动删除。

OLD表主要有以下作用:

它临时保存了删除的记录行

可以从OLD表中检查删除的数据是否满足业务需求

表结构

-- 创建已经毕业的学生表--
CREATE TABLE  graduatedstudent(
id VARCHAR(36) NOT NULL COMMENT '自增编号',
sname VARCHAR(16) NOT NULL COMMENT '学生姓名',
enterTime date NOT NULL COMMENT '入校日期',
leaveTime date NOT NULL COMMENT '离校日期',
learnYear INT(4) DEFAULT NULL COMMENT '在校度过的年限'
)ENGINE = INNODB DEFAULT CHARSET = utf8;


触发器:

CREATE TRIGGER trigger_stu_copy1_delete
BEFORE DELETE
ON stu_copy1
FOR EACH ROW
BEGIN
INSERT INTO graduatedstudent(id,sname,enterTime,leaveTime,learnYear) VALUES(UUID(),OLD.stuname,OLD.enterTime,NOW(),YEAR(NOW())-YEAR(OLD.enterTime));
END;


更新触发器

更新触发器同时拥有OLD和NEW两张临时表:

OLD表记录更新前的记录。

NEW表记录更新后的记录。

例如:

表结构和新增触发器一样,触发器如下:

CREATE  TRIGGER trigger_stu_update
AFTER UPDATE
ON stu_copy1
FOR EACH ROW
BEGIN
INSERT INTO stu_log(id,operationtype,operationid,oldvalue,newvalue,createtime)VALUES
(UUID(),'update',NEW.id
,CONCAT(OLD.stuname,',',OLD.sex,',',OLD.birthday,',',OLD.classname,',',OLD.enterTime)
,CONCAT(NEW.stuname,',',NEW.sex,',',NEW.birthday,',',NEW.classname,',',NEW.enterTime)
,NOW());
END;
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息