存储过程
-- 存储过程基本语法
-- 创建
create procedure p1()
begin
select count(*) from student;
end;
-- 调用
call p1();
-- 查看
select * from information_schema.ROUTINES where ROUTINE_SCHEMA = 'itcast';
show create procedure p1;
-- 删除
drop procedure if exists p1;
在命令行中,执行创建存储过程的 SQL 时,需要通过关键字 delimiter 指定 SQL 语句的
结束符。
delimiter $$
create procedure p1()
beginsql语句;
end$$
一旦设定$$是结束符,那么结束符就一直是$$
变量
系统变量
属于服务器层面,分为全局变量GLOBAL、会话变量SESSION(仅在当前会话打开的那个控制台query有效)
- 查看系统变量
SHOW [ SESSION | GLOBAL ] VARIABLES ; -- 查看所有系统变量
SHOW [ SESSION | GLOBAL ] VARIABLES LIKE '......'; -- 可以通过LIKE模糊匹配方
式查找变量
SELECT @@[SESSION | GLOBAL] 系统变量名; -- 查看指定变量的值
select @@global.autocommit
- 设置系统变量
SET [ SESSION | GLOBAL ] 系统变量名 = 值 ;
SET @@[SESSION | GLOBAL]系统变量名 = 值 ;
用户变量
SET @var_name = expr [, @var_name = expr] ... ;
SET @var_name := expr [, @var_name := expr] ... ;SELECT @var_name := expr [, @var_name := expr] ... ;
SELECT 字段名 INTO @var_name FROM 表名;select count(*) into @mycount from tb_gender;
局部变量
-- 声明局部变量 - declare
-- 赋值
create procedure p2()
begin
declare stu_count int default 0;
select count(*) into stu_count from student;
select stu_count;
end;
call p2();
参数
create procedure p5(inout score double)
beginset score := score * 0.5;select score;
end;set @score = 198;
call p5(@score);
注意后面不能直接call一个数,因为要传递回来,所以要先set一个用户变量
游标
在存储过程中存储多列
存储函数
就是定义输入参数,定义return int deterministic返回
触发器
使用别名 OLD 和 NEW 来引用触发器中发生变化的记录内容,这与其他的数据库是相似的。现在触发器还 只支持行级触发,不支持语句级触发。
create trigger tb_user_update_trigger
after update on tb_user for each row
begin
insert into user_logs(id, operation, operate_time, operate_id, operate_params)
VALUES
(null, 'update', now(), new.id,
concat('更新之前的数据: id=',old.id,',name=',old.name, ', phone=',
old.phone, ', email=', old.email, ', profession=', old.profession,
' | 更新之后的数据: id=',new.id,',name=',new.name, ', phone=',
NEW.phone, ', email=', NEW.email, ', profession=', NEW.profession));
end;
锁
全局锁
读锁不会阻塞其他客户端的读,但是会阻塞写。写锁既会阻塞其他客户端的读,又会阻塞
其他客户端的写。
意向锁
意向共享锁句select ... lock in share mode
与写锁冲突、读锁兼容
意向排它锁insert、update、delete、select...for update
与写锁读锁都冲突
行级锁
行锁
共享锁与共享锁之间兼容,排它锁与其他锁之间冲突
共享锁与排他锁之间不相容
客户端一获取的是 id 为 1 这行的共享锁,客户端二是可以获取 id 为 3 这行的排它锁的,因为不是同一行 数据。 而如果客户端二想获取id 为 1 这行的排他锁,会处于阻塞状态,以为共享锁与排他锁之间互斥。切记这是行锁!!!
无索引行锁升级为表锁
客户端一,根据 name 字段进行更新时, name 字段是没有索引的,如果没有索引,
此时行锁会升级为表锁 ( 因为行锁是对索引项加的锁,而 name 没有索引 ) 。
在客户端一中,开启事务,并执行 update 语句,更新 name 为 Lily 的数据,也就是 id 为 19 的记录 。
然后在客户端二中更新 id 为 3 的记录,却不能直接执行,会处于阻塞状态
间隙锁 临键锁
A. 索引上的等值查询 ( 唯一索引,大概就是主键索引 ) ,给不存在的记录加锁时 , 优化为间隙。
注意间隙锁不包含两头,也就是不包含下面的3和8
B. 索引上的等值查询 ( 非唯一普通索引 ) ,向右遍历时最后一个值不满足查询需求时, next-key
lock 退化为间隙锁。
这是因为普通索引不唯一,所以在左边区间和右边区间都锁住。
C. 索引上的范围查询 ( 唯一索引 )-- 会访问到不满足条件的第一个值为止