MySQL【四】 之 【索引】【视图】【触发器】【存储过程】【函数】
1.索引
索引相当于图书的目录,可以帮助用户快速的找到需要的内容.
数据库利用各种各样的快速定位技术,能够大大提高查询效率。特别是当数据量非常大,查询涉及多个表时,使用索引往往能使查询速度加快成千上万倍.
索引好处:可以提高查询效率,而且是数据量越大效果越明显.
索引缺点:添加数据和删除数据效率低
索引类型:
1.HASH :hash就是一种(key=>value)形式的键值对,允许多个key对应相同的value,但不允许一个key对应多个value,为某一列或几列建立hash索引,就会利用这一列或几列的值通过一定的算法计算出一个hash值,对应一行或几行数据. hash索引可以一次定位,不需要像树形索引那样逐层查找,因此具有极高的效率.
假设创建如下一个表:
CREATE TABLE testhash (
fname VARCHAR(50) NOT NULL,
lname VARCHAR(50) NOT NULL,
KEY USING HASH(fname)
) ENGINE=MEMORY;
包含的数据如下:
假设索引使用hash函数f( ),如下:
f('Arjen') = 2323 f('Baron') = 7437 f('Peter') = 8784 f('Vadim') = 2458 |
此时,索引的结构大概如下:
Slots是有序的,但是记录不是有序的。当你执行
mysql> SELECT lname FROM testhash WHERE fname='Peter';
MySQL会计算’Peter’的hash值,然后通过它来查询索引的行指针。因为f('Peter') = 8784,MySQL会在索引中查找8784,得到指向记录3的指针。
因为索引自己仅仅存储很短的值,所以,索引非常紧凑。Hash值不取决于列的数据类型,一个TINYINT列的索引与一个长字符串列的索引一样大。
2.BTREE: 就是一种将索引值按一定的算法,存入一个树形的数据结构中. 如二叉树一样
索引分类:
1. 普通索引
2.唯一索引
3.主键索引
4.组合索引
5. FULLTEXT:全文索引
目前只有MyISAM引擎支持。而且只有 CHAR、VARCHAR ,TEXT 列上可以创建全文索引.
FULLTEXT索引是按照分词原理建立索引的。西文中,大部分为字母文字,分词可以很方便的按照空格进行分割。但很明显,中文不能按照这种方式进行分词。那又怎么办呢?这个向大家介绍一个Mysql的中文分词插件Mysqlcft,有了它,就可以对中文进行分词,想了解的同学请移步Mysqlcft,当然还有其他的分词插件可以使用。
1.创建 普通索引
1 CREATE index aaa on ren(p_name)
2 添加普通索引
3 注意:index :表示索引 aaa:表示索引的别名, on:表示给哪个表添加索引 ren:表名称,(添加索引的字段,多个字段以","间隔)2.创建 唯一索引
1 CREATE UNIQUE index age on ren(p_age)
2 添加唯一索引
3 注意:unique index :表示唯一索引 aaa:表示索引的别名, on:表示给哪个表添加索引 ren:表名称,(添加索引的字段,多个字段以","间隔)3.创建 主键索引
1 alter table 表名 add primary key(id);
2 添加之间索引
3 注意:主键索引只能有一个4.创建 组合索引
1 create index id_name on ren (id,name)
2 添加组合索引
3 注意: 如上创建组合索引之后,查询:
4 id and name-- 使用索引
5 id -- 使用索引
6 name -- 不使用索引
2.视图
视图是一个虚拟表,其内容由查询定义。同真实的表一样,视图包含一系列带有名称的列和行数据。但是,视图并不在数据库中以存储的数据值集形式存在。行和列数据来自定义视图的查询所引用的表,并且在引用视图时动态生成。
视图好处:
a、简化表之间的联结(把联结写在select中);
b、适当的利用视图可以更清晰地表达查询
c、过滤不想要的数据(select部分)视图能够对机密数据提供安全保护
d、使用视图计算字段值,如汇总这样的值。
1.创建视图
1 #create view 视图名称 as sql 查询语句
2 CREATE view ren_view as select p_id,p_name,p_age,p_leader from ren;2.使用视图
1 select * from 视图名称;3.更新视图数据
1 update ren_view set p_age =99 where p_id = 'p004';4.删除视图数据
1 DELETE from ren_view where p_id = 'p010';5.删除视图
1 drop view ren_view;
3.触发器-trigger
触发器(trigger):监视某种情况,并触发某种操作。
触发器创建语法四要素:1.监视地点(table)
2.监视事件(insert/update/delete)
3.触发时间(after/before)
4.触发事件(insert/update/delete)
1.创建触发器语法
1 create trigger triggerName after/before insert/update/delete
2 on 表名 for each row #这句话是固定的
3
4 begin
5
6 #需要执行的sql语句
7
8 end
9
10 注意1:after/before: 只能选一个 ,after 表示 后置触发, before 表示前置触发
11 注意2:insert/update/delete:只能选一个创建两张表
#商品表
create table goods(
id int primary key auto_increment,
name varchar(20),
num int
);
#订单表
create table order_table(
oid int primary key auto_increment,
gid int,
much int
);
添加3条商品数据
1 insert into g(name,num) values('商品1',10),('商品2',10),('商品3',10);如果我们在没使用触发器之前:假设我们现在卖了3个商品1,我们需要做两件事
1.往订单表插入一条记录
1 insert into o(gid,much) values(1,3);2.更新商品表商品1的剩余数量
update g set num=num-3 where id=1;现在,我们来创建一个触发器:
1 create trigger tg1 after insert on order_table for each row
2
3 begin
4
5 update goods set num = num -3 where id = 1;
6
7 end这时候我们只要执行:
1 insert into order_table(gid,much) values(1,3);会发现商品1的数量变为7了,说明在我们插入一条订单的时候,
触发器自动帮我们做了更新操作。
但现在会有一个问题,因为我们触发器里面num和id都是写死的,所以不管我们买哪个商品,最终更新的都是商品1的数量。比如:我们往订单表再插入一条记录:
insert into o(gid,much) values(2,3);执行完后会发现商品1的数量变4了,而商品2的数量没变,这样显然不是我们想要的结果。我们需要改改我们之前创建的触发器。
我们如何在触发器引用行的值,也就是说我们要得到我们新插入的订单记录中的gid或much的值。
对于insert而言,新插入的行用new来表示,行中的每一列的值用new.列名来表示。
所以现在我们可以这样来改我们的触发器:
create trigger tg2 afert insert on order_table for each row
begin update goods set num = num-new.much where id = new.gid;
new.much 表是被监控的order_table 中的much字段更新后的数据,它的改变进而影响表goods中的num数据的改变 end第二个触发器创建完毕,我们先把第一个触发器删掉
效果图:
#1线自己写了一个触发器,
CREATE trigger tb after UPDATE on order_table
for each ROW
begin
UPDATE goods set num=num-new.much where id=new.gid; new.much 表示被监控的order_table表中的字段much更新后的数据
END1 drop trigger tg1;再来测试一下,插入一条订单记录:
1 insert into order_table(gid,much) values(2,3)执行完发现商品2的数量变为7了,现在就对了。
现在还存在两种情况:
1.当用户撤销一个订单的时候,我们这边直接删除一个订单,我们是不是需要把对应的商品数量再加回去呢?
对于delete而言:原本有一行,后来被删除,想引用被删除的这一行,用old来表示,old.列名可以引用被删除的行的值。
那我们的触发器就该这样写:
create trigger tg3 afert delete on order_table for each row
bigen update goods set num = num + old.much where id = old.gid;(注意这边的变化)
end2.当用户修改一个订单的数量时,我们触发器修改怎么写?
不写了,自己写....
4.存储过程
MySQL数据库在5.0版本后开始支持存储过程,那么什么是存储过程呢?怎么创建、查看和删除存储过程呢?存储过程有什么优点?
1.概念:什么是存储过程:类似于函数(方法),简单的说存储过程是为了完成某个数据库中的特定功能而编写的语句集合,该语句集包括SQL语句(对数据的增删改查)、条件语句和循环语句等。
2. 查看现有的存储过程
1 show procedure status;3 .删除存储过程
1 drop procedure 存储过程名称;4. 调用 存储过程
1 call 存储过程名称(参数1 参数1类型,参数2 参数2类型);5.创建存储过程
1 1#体会封装
2 create procedure p1 ()
3 begin
4 select * from account;
5
6 end1 2#SQL 体会参数
2 create procedure p2(in m int)
3 begin
4 select * from account where money > m;
5 end1 #SQL 体会控制
2 create procedure p3(in x int,in c char(1))
3
4 begin
5
6 if c ='d' then
7
8 select * from account where money >x;
9
10 else
11
12 select * from account where money <x;
13 end if;
14 end#体会循环:计算1-100累加的和,并且返回计算结果.
create procedure p4(inout n int)
begin
DECLARE sum int default 0; -- 设置总和变量,并且指定初始值0
declare i int; -- 声明变量
set i = 0; -- 通过set为变量设置值
while i<=n DO -- 开始循环
set sum = sum +i;
set i = i+1;
end while; -- 结束循环 select sum; -- 提供结果 set n = sum;--将计算结果提供给 输出变量 n; end; -- 调用:
set @n = 100;
call p4(@n);
select @n;存储过程优点:
1、存储过程增强了SQL语言灵活性。存储过程可以使用控制语句编写,可以完成复杂的判断和较复杂的运算,有很强的灵活性;
2、减少网络流量,降低了网络负载。存储过程在数据库服务器端创建成功后,只需要调用该存储过程即可,而传统的做法是每次都将大量的SQL语句通过网络发送至数据库服务器端然后再执行;
3、存储过程只在创造时进行编译,以后每次执行存储过程都不需再重新编译,而一般SQL语句每执行一次就编译一次,所以使用存储过程可提高数据库执行速度。
4、系统管理员通过设定某一存储过程的权限实现对相应的数据的访问权限的限制,避免了非授权用户对数据的访问,保证了数据的安全。
5.函数
MySQL提供的内建函数:
更多函数: 官方猛击这里
1、自定义函数
CREATE FUNCTION fun1(i1 int,i2 int) RETURNS INT //设置返回类型 BEGIN DECLARE sum int default 0;
set sum = i1+i2;
RETURN(sum); //返回结果 end2.调用自定义函数
#直接调用自定义函数
select fun1(1,5); #在sql语句中使用自定义函数
select fun1(参数1,参数2),name from 表名3.删除自定义函数
drop FUNCTION fun_name;