MySQL 拓展

MySQL 拓展

视图

本身是一个虚拟表,它的数据来自于表,通过执行时动态生成,占用较小,只保存了sql逻辑,不保存查询结果。临时表

场景:多个地方用到同样的查询结果;该查询结果使用的sql语句较复杂

create view 视图名
as
查询语句;

create or replace view 视图名
as
查询语句;
alter view 视图名
as
查询语句

drop view 视图1,视图2,...;

desc 视图名;
show create view 视图名;
CREATE VIEW my_v1
AS
SELECT studentname,majorname
FROM student s
INNER JOIN major m
ON s.majorid=m.majorid
WHERE s.majorid=1;

注意:视图一般用于查询的,而不是更新的,所以具备以下特点的视图都不允许更新

  1. 包含分组函数、group by、distinct、having、union、
  2. join
  3. 常量视图
  4. where 后的子查询用到了 from 中的表
  5. 用到了不可更新的视图

变量

系统变量

变量由系统提供的,不用自定义

全局变量:服务器层面上的,必须拥有super权限才能为系统变量赋值,作用域为整个服务器,也就是针对于所有连接(会话)有效

查看所有全局变量
SHOW GLOBAL VARIABLES;
查看满足条件的部分系统变量
SHOW GLOBAL VARIABLES LIKE '%char%';
查看指定的系统变量的值
SELECT @@global.autocommit;
为某个系统变量赋值
SET @@global.autocommit=0;
SET GLOBAL autocommit=0;

会话变量:服务器为每一个连接的客户端都提供了系统变量,作用域为当前的连接(会话)

查看所有会话变量
SHOW SESSION VARIABLES;
查看满足条件的部分会话变量
SHOW SESSION VARIABLES LIKE '%char%';
查看指定的会话变量的值
SELECT @@autocommit;
SELECT @@session.tx_isolation;
为某个会话变量赋值
SET @@session.tx_isolation='read-uncommitted';
SET SESSION tx_isolation='read-committed';

如果没有显式声明 global 还是 session,则默认是 session

自定义变量

用户变量

  • 作用域:针对于当前连接(会话)生效
  • 位置:begin end里面,也可以放在外面
①声明并赋值:
set @变量名=;set @变量名:=;select @变量名:=;

②更新值
方式一:
	set @变量名=;set @变量名:=;select @变量名:=;
方式二:
	select xx into @变量名 from;

③使用
select @变量名;

局部变量

  • 作用域:仅仅在定义它的 begin end中有效
  • 位置:只能放在 begin end中,而且只能放在第一句
①声明
declare 变量名 类型 【default 值】;
②赋值或更新
方式一:
	set 变量名=;set 变量名:=;select @变量名:=;
方式二:
	select xx into 变量名 from;
③使用
select 变量名;
作用域 定义位置 语法
用户变量 当前会话 会话的任何地方 加@符号,不用指定类型
局部变量 定义它的BEGIN END中 BEGIN END的第一句话 一般不用加@,需要指定类型

数据库存储过程

数据库存储过程:就是一组SQL语句集,功能强大,可以实现一些比较复杂的逻辑功能,类似于JAVA语言中的方法。

存储过程跟触发器有点类似,都是一组SQL集,但是存储过程是主动调用的,且功能比触发器更加强大,触发器是某件事触发后自动调用;

创建

create procedure 存储过程名(参数模式 参数名 参数类型)
begin
		存储过程体
end

注意

  1. 参数模式:in、out、inout,其中in可以省略
  2. 存储过程体的每一条sql语句都需要用分号结尾
  3. in、out、inout都可以在一个存储过程中带多个

结束标记

使用 delimiter 指定新的结束标记

delimiter $

调用

call 存储过程名(实参列表)
举例:
调用in模式的参数:call sp1(‘值’);
调用out模式的参数:set @name; call sp1(@name);select @name;
调用inout模式的参数:set @name=; call sp1(@name); select @name;

查看

show create procedure 存储过程名;

删除

drop procedure 存储过程名;

下面创建一个名为num_from_employee的存储过程.

CREATE PROCEDURE num_from_employee (IN emp_id INT, OUT count_num INT ) 
     READS SQL DATA 
     BEGIN 
       SELECT COUNT(*) INTO count_num 
       FROM employee 
       WHERE d_id=emp_id ; 
     END
     
#调用
SET @cnum ; # 不定义直接用也可以
CALL num_from_employee(123,@cnum);

存储过程名称为 num_from_employee;输入变量为emp_id;输出变量为count_num。SELECT语句从employee表查询d_id值等于emp_id的记录,并用COUNT(*)计算d_id值相同的记录的条数,最后将计算结果存入count_num中。

函数

创建

create function 函数名(参数名 参数类型) returns  返回类型
begin
	函数体
end

注意:函数体中肯定需要有return语句

#案例1:根据员工名,返回它的工资;有参有返回
CREATE FUNCTION myf2(empName VARCHAR(20)) RETURNS DOUBLE
BEGIN
	SET @sal=0;#定义用户变量 
	SELECT salary INTO @sal   #赋值
	FROM employees
	WHERE last_name = empName;	
	RETURN @sal;
END $

SELECT myf2('k_ing') $

调用

select 函数名(实参列表);

查看

show create function 函数名;

删除

drop function 函数名;
关键字 调用语法 返回值 应用场景
函数 FUNCTION SELECT 函数() 只能是一个 一般用于查询结果为一个值并返回时
存储过程 PROCEDURE CALL 存储过程() 可以有0个或多个 一般用于更新

流程控制

顺序结构:程序从上往下依次执行

分支结构:程序按条件进行选择执行,从两条或多条路径中选择一条执行

循环结构:程序满足一定条件下,重复执行一组语句

分支结构

if 函数

  • 功能:实现简单双分支
  • 语法:if(条件,值1,值2)
  • 位置:可以作为表达式放在任何位置

case 结构

  • 功能:实现多分支
  • 位置:可以放在任何位置,
    • 如果放在begin end 外面,作为表达式结合着其他语句使用
    • 如果放在begin end 里面,一般作为独立的语句使用
语法1case 表达式或字段
when1 then 语句1;
when2 then 语句2..
else 语句n;
end [case];

语法2case 
when 条件1 then 语句1;
when 条件2 then 语句2..
else 语句n;
end [case];

if 结构

  • 功能:实现多分支
  • 位置:只能放在begin end中
if 条件1 then 语句1;
elseif 条件2 then 语句2;
...
else 语句n;
end if;

循环结构

while

名称可以不写,写了就成对使用,记得冒号

【名称:】while 循环条件 do
		循环体
end while 【名称】;

loop

注意死循环

【名称:】loop
		循环体
end loop 【名称】;

repeat

【名称:】repeat
		循环体
until 结束条件 
end repeat 【名称】;

比较

位置:只能放在begin end中

特点:都能实现循环结构

对比:

  • 这三种循环都可以省略名称,但如果循环中添加了循环控制语句(leave或iterate)则必须添加名称
  • loop 一般用于实现简单的死循环
  • while 先判断后执行
  • repeat 先执行后判断,无条件至少执行一次

循环控制语句

  • leave:类似于break,用于跳出所在的循环
  • iterate:类似于continue,用于结束本次循环,继续下一次
/*一、已知表stringcontent
其中字段:
id 自增长
content varchar(20)

向该表插入指定个数的,随机的字符串
*/
DROP TABLE IF EXISTS stringcontent;
CREATE TABLE stringcontent(
	id INT PRIMARY KEY AUTO_INCREMENT,
	content VARCHAR(20)
	
);
DELIMITER $
CREATE PROCEDURE test_randstr_insert(IN insertCount INT)
BEGIN
	DECLARE i INT DEFAULT 1;
	DECLARE str VARCHAR(26) DEFAULT 'abcdefghijklmnopqrstuvwxyz';
	DECLARE startIndex INT;#代表初始索引
	DECLARE len INT;#代表截取的字符长度
	WHILE i<=insertcount DO
		SET startIndex=FLOOR(RAND()*26+1);#代表初始索引,随机范围1-26
		SET len=FLOOR(RAND()*(20-startIndex+1)+1);#代表截取长度,随机范围1-(20-startIndex+1)
		INSERT INTO stringcontent(content) VALUES(SUBSTR(str,startIndex,len));
		SET i=i+1;
	END WHILE;

END $

CALL test_randstr_insert(10)$

触发器

触发器(TRIGGER)是由事件来触发某个操作。这些事件包括INSERT语句、UPDATE语句和DELETE语句。当数据库系统执行这些事件时,会激活促发其执行相应的操作。参考

CREATE TRIGGER 触发器名 BEFORE|AFTER 触发事件
ON 表名 FOR EACH ROW
BEGIN
    执行语句列表
END

触发事件

  • INSERT 型触发语句:INSERT,LOAD DATA,REPLACE
  • UPDATE 型触发语句:UPDATE
  • DELETE 型触发语句:DELETE,REPLACE

当在users中插入一条数据,就会在logs中生成一条日志信息。

DELIMITER $
CREATE TRIGGER user_log AFTER INSERT ON users FOR EACH ROW
BEGIN
    DECLARE s1 VARCHAR(40)character set utf8;
    DECLARE s2 VARCHAR(20) character set utf8;#后面发现中文字符编码出现乱码,这里设置字符集
    SET s2 = " is created";
    SET s1 = CONCAT(NEW.name,s2);     #函数CONCAT可以将字符串连接
    INSERT INTO logs(log) values(s1);
END $
DELIMITER ;

定时任务

mysql5.1.6 增加了一个事件调度器(Event Scheduler),可以做定时任务(定时删除记录,定时数据统计),取代之前系统的计划任务。mysql事件调度器可以精确到每秒执行一个任务。参考

事件调度器与触发器的区别:事件调度器是基于特定时间周期来触发执行某些任务,触发器是基于某个表产生的事件来触发。

查看是否开启

show variables like 'event_scheduler';

开启事件调度器

set global event_scheduler = on;

当mysql重启后,会自动关闭。如果需要一直开启,需要在my.ini中配置如下:event_scheduler = on

创建事件语法

CREATE EVENT [IF NOT EXISTS ] event_name
ON SCHEDULE schedule
[ ON COMPLETION [ NOT ] PRESERVE ]
[ ENABLE | DISABLE ]
[ COMMENT '注释' ]
DO SQL语句;
 
schedule : AT TIMESTAMP [+ INTERVAL interval ] | EVERY interval [ STARTS TIMESTAMP ] [ ENDS TIMESTAMP ]
interval : quantity { YEAR | QUARTER | MONTH | DAY |
           HOUR | MINUTE | WEEK | SECOND |
           YEAR_MONTH | DAY_HOUR | DAY_MINUTE | DAY_SECOND |
           HOUR_MINUTE | HOUR_SECOND | MINUTE_SECOND }

关闭事件

ALTER EVENT event_name DISABLE;

开启事件

ALTER EVENT event_name ENABLE;

删除事件

DROP EVENT [IF EXISTS ] event_name;

查看所有事件

SHOW EVENTS;

查看定期任务

SELECT event_name,event_definition,interval_value,interval_field,status 
FROM information_schema.EVENTS;

定时规则

  • 周期执行–关键字 EVERY
  • 在具体某个时间执行–关键字 AT
  • 在某个时间段执行–关键字 STARTS ENDS

示例

事件类型有两种,一种是间隔触发,一种是特定时间触发

DROP EVENT IF EXISTS event_test;
CREATE EVENT event_test
ON SCHEDULE EVERY 1 SECOND STARTS '2017-08-22 11:57:00' ENDS '2017-08-22 12:00:00'
ON COMPLETION PRESERVE
ENABLE
COMMENT '每隔一秒向test表插入记录'
DO INSERT INTO test VALUES(NULL, now());
DROP EVENT IF EXISTS event_test2;
CREATE EVENT event_test2
ON SCHEDULE AT '2017-08-22 12:01:00'
ON COMPLETION PRESERVE
ENABLE
COMMENT '指定时间向test表插入记录'
DO INSERT INTO test VALUES(999999, now());
on schedule every 1 week //每周执行1次

on schedule at current_timestamp()+interval 5 day //5天后执行
on schedule at '2019-01-01 00:00:00' //在2019年1月1日,0点整执行

on schedule every 1 day starts current_timestamp()+interval 5 day ends current_timestamp()+interval 1 month //5天后开始每天都执行执行到下个月底
on schedule every 1 day ends current_timestamp()+interval 5 day //从现在起每天执行,执行5天
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章