mysql高级

目录

1. mysql体系结构

2. 存储引擎

2.1 存储引擎概述

2.2.1 InnoDB

2.2.2 MyISAM

2.2.3 存储引擎选择

2. 存储过程。

2.1 存储过程和函数概述

2.2 创建存储过程

2.3 调用存储过程

2.4 查看存储过程

2.5 删除存储过程

2.6 语法

2.6.1 变量

2.6.2 if条件判断

2.6.3 传递参数

2.6.4 case结构

2.6.5 while循环

2.6.6 repeat结构

2.6.7 游标/光标 (了解)--能看懂

2.7 存储函数 ---存储过程 函数:函数有返回值。


1. mysql体系结构

 

1) 连接层

主要完成一些类似于连接处理、授权认证、及相关的安全方案。在该层上引入了线程池的概念,为通过认证安全接入的客户端提供线程。同样在该层上可以实现基于SSL的安全链接。服务器也会为安全接入的每个客户端验证它所具有的操作权限。

2) 服务层

第二层架构主要完成大多数的核心服务功能,如SQL接口,并完成缓存的查询,SQL的分析和优化,部分内置函数的执行。所有跨存储引擎的功能也在这一层实现,如 过程、函数等。在该层,服务器会解析查询并创建相应的内部解析树,并对其完成相应的优化如确定表的查询的顺序,是否利用索引等, 最后生成相应的执行操作。如果是select语句,服务器还会查询内部的缓存,如果缓存空间足够大,这样在解决大量读操作的环境中能够很好的提升系统的性能。

3) 引擎层 [存储引擎]

存储引擎层, 存储引擎真正的负责了MySQL中数据的存储和提取,服务器通过API和存储引擎进行通信。不同的存储引擎具有不同的功能,这样我们可以根据自己的需要,来选取合适的存储引擎。

4)存储层

数据存储层, 主要是将数据存储在文件系统之上,并完成与存储引擎的交互。

和其他数据库相比,MySQL有点与众不同,它的架构可以在多种不同场景中应用并发挥良好作用。主要体现在存储引擎上,插件式的存储引擎架构,将查询处理和其他的系统任务以及数据的存储提取分离。这种架构可以根据业务的需求和实际需要选择合适的存储引擎

mysql体系结构:

1. 连接层:

2. 服务层:
3. 存储引擎:

4. 存储层: mysql数据全都存在在文件上。

2. 存储引擎

2.1 存储引擎概述

​ 和大多数的数据库不同, MySQL中有一个存储引擎的概念, 针对不同的存储需求可以选择最优的存储引擎

​ 存储引擎就是存储数据,建立索引,更新查询数据等等技术的实现方式 。存储引擎是==基于表的==,而不是基于库的。

​ Oracle,SqlServer 等数据库只有一种存储引擎。MySQL提供了插件式的存储引擎架构。所以MySQL存在多种存储引擎,可以根据需要使用相应引擎,或者编写存储引擎。

可以通过指定 show engines , 来查询当前数据库支持的存储引擎 :

 

创建新表时如果不指定存储引擎,那么系统就会使用默认的存储引擎,MySQL5.5之前的默认存储引擎是MyISAM,5.5之后就改为了InnoDB。

查看Mysql数据库默认的存储引擎 , 指令 :

 show variables like '%storage_engine%' ;

 

2.2.1 InnoDB

​ InnoDB存储引擎是Mysql的默认存储引擎。InnoDB存储引擎提供了具有提交、回滚、崩溃恢复能力的事务安全。但是对比MyISAM的存储引擎,InnoDB写的处理效率差一些,并且会占用更多的磁盘空间以保留数据和索引。

InnoDB存储引擎不同于其他存储引擎的特点 :

事务控制

create table goods_innodb(
	id int NOT NULL AUTO_INCREMENT,
	name varchar(20) NOT NULL,
    primary key(id)
)ENGINE=innodb DEFAULT CHARSET=utf8;

create table goods_MyISAM(
	id int NOT NULL AUTO_INCREMENT,
	name varchar(20) NOT NULL,
    primary key(id)
)ENGINE=MyISAM DEFAULT CHARSET=utf8;

 

start transaction;

insert into goods_innodb(id,name)values(null,'Meta20');

commit;


start transaction;

insert into goods_MyISAM(id,name)values(null,'Meta20');

commit;

 测试,发现在InnoDB中是存在事务的 ;

外键约束

​ MySQL支持外键的存储引擎==只有InnoDB==, 在创建外键的时候, 要求父表必须有对应的索引 , 子表在创建外键的时候, 也会自动的创建对应的索引。

​ 下面两张表中 , country_innodb是父表 , country_id为主键索引,city_innodb表是子表,country_id字段为外键,对应于country_innodb表的主键country_id 。

create table country_innodb(
	country_id int NOT NULL AUTO_INCREMENT,
    country_name varchar(100) NOT NULL,
    primary key(country_id)
)ENGINE=InnoDB DEFAULT CHARSET=utf8;


create table city_innodb(
	city_id int NOT NULL AUTO_INCREMENT,
    city_name varchar(50) NOT NULL,
    country_id int NOT NULL,
    primary key(city_id),
    key idx_fk_country_id(country_id),
    CONSTRAINT `fk_city_country` FOREIGN KEY(country_id) REFERENCES country_innodb(country_id) ON DELETE RESTRICT ON UPDATE CASCADE
)ENGINE=InnoDB DEFAULT CHARSET=utf8;



insert into country_innodb values(null,'China'),(null,'America'),(null,'Japan');
insert into city_innodb values(null,'Xian',1),(null,'NewYork',2),(null,'BeiJing',1);




在创建索引时, 可以指定在删除、更新父表时,对子表进行的相应操作,包括 RESTRICT、CASCADE、SET NULL 和 NO ACTION。

RESTRICT和NO ACTION相同, 是指限制在子表有关联记录的情况下, 父表不能更新;

CASCADE表示父表在更新或者删除时,更新或者删除子表对应的记录;

SET NULL 则表示父表在更新或者删除的时候,子表的对应字段被SET NULL 。

针对上面创建的两个表, 子表的外键指定是ON DELETE RESTRICT ON UPDATE CASCADE 方式的, 那么在主表删除记录的时候, 如果子表有对应记录, 则不允许删除, 主表在更新记录的时候, 如果子表有对应记录, 则子表对应更新 。

表中数据如下图所示 :

 删除country_id为1 的country数据:

 delete from country_innodb where country_id = 1;

 更新主表country表的字段 country_id :

update country_innodb set country_id = 100 where country_id = 1;

更新后, 子表的数据信息为 :

存储方式 /var/lib/mysql/demo01

InnoDB 存储表和索引有以下两种方式 :

①. 使用共享表空间存储, 这种方式创建的表的表结构保存在.frm文件中, 数据和索引保存在 innodb_data_home_dir 和 innodb_data_file_path定义的表空间中,可以是多个文件。

②. 使用多表空间存储, 这种方式创建的表的表结构仍然存在 .frm 文件中,但是每个表的数据和索引单独保存在 .ibd 中。

 

 

2.2.2 MyISAM

​ MyISAM 不支持事务、也不支持外键,其优势是访问的速度快,对事务的完整性没有要求或者以SELECT、INSERT为主的应用基本上都可以使用这个引擎来创建表 。有以下两个比较重要的特点:

不支持事务

create table goods_myisam(
	id int NOT NULL AUTO_INCREMENT,
	name varchar(20) NOT NULL,
    primary key(id)
)ENGINE=myisam DEFAULT CHARSET=utf8;

 通过测试,我们发现,在MyISAM存储引擎中,是没有事务控制的 ;

**不支持外键**

create table country_myisam(
	country_id int NOT NULL AUTO_INCREMENT,
    country_name varchar(100) NOT NULL,
    primary key(country_id)
)ENGINE=MyISAM DEFAULT CHARSET=utf8;


create table city_myisam(
	city_id int NOT NULL AUTO_INCREMENT,
    city_name varchar(50) NOT NULL,
    country_id int NOT NULL,
    primary key(city_id),
    key idx_fk_country_id(country_id),
    CONSTRAINT `fk_city_country` FOREIGN KEY(country_id) REFERENCES country_myisam(country_id) ON DELETE RESTRICT ON UPDATE CASCADE
)ENGINE=MyISAM DEFAULT CHARSET=utf8;



insert into country_myisam values(null,'China'),(null,'America'),(null,'Japan');
insert into city_myisam values(null,'Xian',1),(null,'NewYork',2),(null,'BeiJing',1);

文件存储方式

每个MyISAM在磁盘上存储成3个文件,其文件名都和表名相同,但拓展名分别是 :

.frm (存储表定义);

.MYD(MYData , 存储数据);

.MYI(MYIndex , 存储索引);

myisam

 

innodb: 支持事务和外键,而且表结构存在一个文件中,索引和数据存储在idb文件中

myisam: 不支持事务和外键,它的表结构存在在frm中,索引和数据分别存在在myi和myd文件中

2.2.3 存储引擎选择

 

2. 存储过程。

2.1 存储过程和函数概述

​ 存储过程和函数是 事先经过编译并存储在数据库中的一段 SQL 语句的集合,调用存储过程和函数可以简化应用开发人员的很多工作,减少数据在数据库和应用服务器之间的传输,对于提高数据处理的效率是有好处的。

​ 存储过程和函数的区别在于函数必须有返回值,而存储过程没有。

​ 函数 : 是一个有返回值的过程 ;

​ 过程 : 是一个没有返回值的函数 ;

2.2 创建存储过程

CREATE PROCEDURE procedure_name ([proc_parameter[,...]])
begin
    -- SQL语句
end ;

示例 :

delimiter $

create procedure pro_test1()
begin
	select 'Hello Mysql' ;
end$

delimiter ;

2.3 调用存储过程

call procedure_name() ;   

2.4 查看存储过程

-- 查询db_name数据库中的所有的存储过程
select name from mysql.proc where db='db_name';


-- 查询存储过程的状态信息
show procedure status;


-- 查询某个存储过程的定义
show create procedure test.pro_test1 \G;

2.5 删除存储过程

2.6 语法

存储过程是可以编程的,意味着可以使用变量,表达式,控制结构 , 来完成比较复杂的功能。

2.6.1 变量

  • DECLARE

    通过 DECLARE 可以定义一个局部变量,该变量的作用范围只能在 BEGIN…END 块中。

DECLARE var_name[,...] type [DEFAULT value]

示例 :

 delimiter $

 create procedure pro_test2() 
 begin 
 	declare num int default 5;
 	select num+ 10; 
 end$

 delimiter ; 
  • SET

直接赋值使用 SET,可以赋常量或者赋表达式,具体语法如下:

SET var_name = expr [, var_name = expr] ...

示例 :

  DELIMITER $
  
  CREATE  PROCEDURE pro_test3()
  BEGIN
  	DECLARE NAME VARCHAR(20);
  	SET NAME = 'MYSQL';
  	SELECT NAME ;
  END$
  
  DELIMITER ;

也可以通过select ... into 方式进行赋值操作 :

DELIMITER $

CREATE  PROCEDURE pro_test5()
BEGIN
	declare  countnum int;
	select count(*) into countnum from city;
	select countnum;
END$

DELIMITER ;

2.6.2 if条件判断

语法结构 :

if search_condition then statement_list

    [elseif search_condition then statement_list] ...
    
    [else statement_list]
    
end if;

需求:

根据定义的身高变量,判定当前身高的所属的身材类型

    180 及以上 ----------> 身材高挑

    170 - 180  ---------> 标准身材

    170 以下  ----------> 一般身材

示例 :

delimiter $

create procedure pro_test6()
begin
  declare  height  int  default  175; 
  declare  description  varchar(50);
  if  height >= 180  then
    set description = '身材高挑';
  elseif height >= 170 and height < 180  then
    set description = '标准身材';
  else
    set description = '一般身材';
  end if;
  
  select description ;
end$

delimiter ;

调用结果为 :

2.6.3 传递参数

语法格式 :

create procedure procedure_name([in/out/inout] 参数名   参数类型)
...


IN :   该参数可以作为输入,也就是需要调用方传入值 , 默认
OUT:   该参数作为输出,也就是该参数可以作为返回值
INOUT: 既可以作为输入参数,也可以作为输出参数

IN - 输入

需求 :

根据定义的身高变量,判定当前身高的所属的身材类型

示例 :

delimiter $

create procedure pro_test5(in height int)
begin
    declare description varchar(50) default '';
  if height >= 180 then
    set description='身材高挑';
  elseif height >= 170 and height < 180 then
    set description='标准身材';
  else
    set description='一般身材';
  end if;
  select concat('身高 ', height , '对应的身材类型为:',description);
end$

delimiter ;

需求 :

根据传入的身高变量,获取当前身高的所属的身材类型

create procedure pro_test5(in height int , out description varchar(100))
begin
  if height >= 180 then
    set description='身材高挑';
  elseif height >= 170 and height < 180 then
    set description='标准身材';
  else
    set description='一般身材';
  end if;
end$   

调用:

call pro_test5(168, @description)$

select @description$

@description : 这种变量要在变量名称前面加上“@”符号,叫做用户会话变量,代表整个会话过程他都是有作用的,这个类似于全局变量一样。

@@global.sort_buffer_size : 这种在变量前加上 "@@" 符号, 叫做 系统变量

2.6.4 case结构

switch ()

case

case

default:

语法结构 :

方式一 : 

CASE case_value

  WHEN when_value THEN statement_list
  
  [WHEN when_value THEN statement_list] ...
  
  [ELSE statement_list]
  
END CASE;

----传递一个int类型的数字 如果为1 则输出星期一  
方式二 : 

CASE

  WHEN search_condition THEN statement_list
  
  [WHEN search_condition THEN statement_list] ...
  
  [ELSE statement_list]
  
END CASE;

需求:

给定一个月份, 然后计算出所在的季度  

输入一个数字(1~7) 根据数字判断星期几  

输入一个月份  判断这个有几天2月28天。

示例 :

delimiter $


create procedure pro_test9(month int)
begin
  declare result varchar(20);
  case 
    when month >= 1 and month <=3 then 
      set result = '第一季度';
    when month >= 4 and month <=6 then 
      set result = '第二季度';
    when month >= 7 and month <=9 then 
      set result = '第三季度';
    when month >= 10 and month <=12 then 
      set result = '第四季度';
  end case;
  
  select concat('您输入的月份为 :', month , ' , 该月份为 : ' , result) as content ;
  
end$


delimiter ;

2.6.5 while循环

while(条件){

}

需求:

计算从1加到n的数的和值   

示例 :
 

delimiter $

create procedure pro_test8(n int)
begin
  declare total int default 0;
  declare num int default 1;
  while num<=n do
    set total = total + num;
    set num = num + 1;
  end while;
  select total;
end$

delimiter ;

2.6.6 repeat结构

do{}while()

有条件的循环控制语句, 当满足条件的时候退出循环 。while 是满足条件才执行,repeat 是满足条件就退出循环。

语法结构 :

REPEAT

  statement_list

  UNTIL search_condition  --不要加分号

END REPEAT;

需求:

计算从1加到n的值 

示例 :

delimiter $

create procedure pro_test10(n int)
begin
  declare total int default 0;
  
  repeat 
    set total = total + n;
    set n = n - 1;
    until n=0  
  end repeat;
  
  select total ;
  
end$


delimiter ;

2.6.7 游标/光标 (了解)--能看懂

游标是用来存储查询结果集的数据类型 , 在存储过程和函数中可以使用游标对结果集进行循环的处理。游标的使用包括游标的声明、OPEN、FETCH 和 CLOSE,其语法分别如下。

声明游标:

DECLARE cursor_name CURSOR FOR select_statement ; -- select语句

OPEN 游标:

OPEN cursor_name ;

 FETCH 游标:

FETCH cursor_name INTO var_name [, var_name] ...

CLOSE 游标:

CLOSE cursor_name ;

示例 :

初始化脚本:

create table emp(
  id int(11) not null auto_increment ,
  name varchar(50) not null comment '姓名',
  age int(11) comment '年龄',
  salary int(11) comment '薪水',
  primary key(`id`)
)engine=innodb default charset=utf8 ;

insert into emp(id,name,age,salary) values(null,'金毛狮王',55,3800),(null,'白眉鹰王',60,4000),(null,'青翼蝠王',38,2800),(null,'紫衫龙王',42,1800);
create PROCEDURE p13()
begin
   DECLARE n varchar(20);
	 DECLARE s int;
	 DECLARE has_data int default 1;
	 -- 声明游标
   DECLARE my CURSOR for select name,salary from emp;
	 -- 
	 DECLARE EXIT HANDLER FOR NOT FOUND set has_data = 0;
	 create table if not EXISTS tb_my(
		 id int primary key  auto_increment,
		 name varchar(20),
		 salary int
	 );
	 
	 -- 开启游标
	 open my;
	 
	 while has_data=1 do
	    -- 取出游标的数据 
	    FETCH my INTO n,s;
			insert into tb_my(name,salary) values(n,s);
	 end while;
   
   close my;
end;

通过循环结构 , 获取游标中的数据 :

 

DELIMITER $

create procedure pro_test12()
begin
  DECLARE id int(11);
  DECLARE name varchar(50);
  DECLARE age int(11);
  DECLARE salary int(11);
  DECLARE has_data int default 1;
  
  DECLARE emp_result CURSOR FOR select * from emp;
  -- 若没有数据返回,程序继续,并将变量has_data设为0 
  DECLARE EXIT HANDLER FOR NOT FOUND set has_data = 0;
  
  open emp_result;
  
  repeat 
    fetch emp_result into id , name , age , salary;
    select concat('id为',id, ', name 为' ,name , ', age为 ' ,age , ', 薪水为: ', salary);
    until has_data = 0
  end repeat;
  
  close emp_result;
end$

DELIMITER ; 

2.7 存储函数 ---存储过程 函数:函数有返回值。

语法结构:

CREATE FUNCTION function_name([param type ... ]) 
RETURNS type 
BEGIN
	...
END;

案例 :

定义一个存储函数, 请求满足条件的总记录数 ;

delimiter $

create function count_city(countryId int)
returns int
begin
  declare cnum int ;
  
  select count(*) into cnum from city where country_id = countryId;
  
  return cnum;
end$

delimiter ;

调用:

select count_city(1);

select count_city(2);

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值