第3节. 函数存储过程和触发器和用户管理
函数-例1
创建函数
查看函数列表
函数是保存在mysql.proc表中的
排版换一下
删除函数
函数-例2
上图的注意点:改变以往;分号作为一个命令去断句执行的行为。而//才是断句。
然后最后结尾又改回去了,所以DELIMITER是一个全局命令。类似交换机的user-interface里的screen-length
创建函数deleteByid,并传递参数uid,类型是SMALLINT 正数, RETRUNS返回的是字符串
BEGIN和END是标明函数体,如果简单的一句话搞定就不用写BEGIN和END,但是多句就不行了。
对比,跑函数之前的students里的行数是21
跑一下函数后的行数是
第10行没了
函数里 赋值的方法①:set a =x 👇
注意
END// DELIMITER; 其实是错误的写法,它表示已“END // DELIMITER;”结束的,而不是以//结束。
函数里赋值方法②:select into xxx
DELIMITER //
CREATE FUNCTION deleteById(uid SMALLINT UNSIGNED) RETURNS VARCHAR(20)
BEGIN
DELETE FROM students WHERE stuid = uid;
RETURN (SELECT COUNT(stuid) FROM students);
END//
DELIMITER ;
可以改成
DELIMITER //
CREATE FUNCTION deleteById2(uid SMALLINT UNSIGNED) RETURNS VARCHAR(20)
BEGIN
DECLARE x int;
DELETE FROM students WHERE stuid = uid;
SELECT COUNT(stuid) FROM students INTO x; # 这里是将select的结果放到了x变量里,这也是一种赋值。
RETURN x;
END//
DELIMITER ;
👆DECLARE申明看来要放在函数体的最前面,紧跟着BEGIN才行。
存储过程,更似shell里的函数
调用的时候比上面的讲的函数更像shell里的函数。
IN是给存储过程找个函数功能传递参数,是传进去
OUT是传出来
INOUT是双向的。
存储过程的案例
create创建、call执行 存储过程
show procedure status;查看👇
注意对比函数的type
mysql库里也是存放了很多重要信息的:比如用户账号、还这里看到myql.proc里的函数、存储过程。
所以备份一定是要备份的。
存储过程参数的传递
注意如果换一个数据库就会报错,需要指定找个存储过程在哪个库里执行
自定义变量在FUNCTION和PRODECURE里的类型
1、局部变量:var 这种
2、全局变量:@var 这种
理解一下上面的mysql里的脚本,哈哈
变量是会话级别的变量,就是说 退出mysql的当前交互,变量就没了
看下out参数的效果,从函数里传出来给到了全局变量。
上图中的row_count()函数是上一次命令更改了多少行的意思。
本例中就是 select row_count() into num;上一条cli,也就是DELETE xxx 更改了18行。
同样测一下
流程控制--存储过程和函数中可以使用IF CASE这些语句,这些专业叫法叫做“流程控制”
LEAVE相当于break
ITERATE相当于continue
触发器--准确来讲应该叫事件触发器
举例:比如你在jd购买了100个手机,下单了,那么库存里就要去掉100个【手机,所以事件就是下单100个,触发就是库存里自动减去100个。
DEFINER 是以什么身份来执行
TRIGGER就是定义触发器的名称
BEFORE 在 INSERT|UPDATE|DELETE之前进行的动作,换句话说就是在你增、改、删之前触发了某个动作,实际上就是不会去执行增、改、删了。就是说BEFORE就是用自定义的动作来代替trigger_event事件了。
触发器示例
附带主键的定义写法补充
一般是在定义字段的时候 比如 stu_id INT(11) NOT NULL AUTO_INCREMENT PRIMARY KEY,这样后跟一个主键来定义。
也可以单独PRIMARY KEY(stuid)去定义主键,那么这种是一般用来定义复合主键的。
做两个表student_info和student_count两个表供触发器来测试效果,
然后👇做两个触发器:
插入一行记录后再查看
可见触发器生效了,因为触发器就是检测到该表的row数量,insert就是将另一个表student_count +1
插入两行,就是增加2个计数
而删掉一行,就计数减一
触发器trigger是放在information_schema里的triggers表里的。
但是information_schema库 并不是磁盘上的文件,所有在磁盘上以文件形式存在的库👇
information_schema是在内存里,所以理论上在information_schema里的后果就是重启mysql服务后触发器丢失。但是我甚至重启centos后发现触发器还在!说明其实触发器还在其他地方存放
如果将teachers表里的TID=3的那行删掉,那么students表里的TearcherID=3的怎么办?理论上是不让删的,
这个时候就会有一种做法--叫 级联删除,就是上面的teachers表里的删了,下面students里的涉及对应老师的那些行也都删了。
但其实,好多公司规范里是不让用外键和级联的。阿里的JAVA开发手册里有提到👇
用户账号和权限管理
mysql新的版本,password不是放在这里的,可能放在authentication_string里。
删除drop好了
改密码-方法1
看下passwrod函数:加密口令的方法,password()就是加密口令的。
改密码👇
密码必须加密
看个localhost的坑,生产中也是要关闭反向解析的。
先说结论,就是localhost和127.0.0.1不是一回事,举例
现在有两个root,一个是root@localhost,一个是root@127.0.0.1
然后使用root@127.0.0.1这个账号和centos这个密码登入
发现明明是127,结果被反向解析成localhost,然后localhost的密码又不是centos,所以deny了
关闭反向解析,让127.0.0.1回归IP,就可以对上root@127.0.0.1 centos这个账号密码了
然后去配置文件做永久关闭就行了,这里OFF就是做解析了,ON就是不做解析。
skip_name_resolve 是忽略名词解析,ON,就是打开就是忽略的意思。
然后故障就解决了
改密码-老的方法2失灵了
验证很简单啊,之前view也学过,
可以用alert就可以了
忘记root密码-破解
1、最粗暴的方法就是,肯定不能用了
rm -rf /var/lib/mysql/* 这样数据里的所有东西都没了,重启服务后,自动初始化一些必要的库会。
2、正常方法
重启后就可以不用密码了
但是此时远程用户也同样不用输入密码就直接进来了
这就不太好了,这就需要开启维护模式--也就是只能本地连接,远程就无法连接了如下👇
PS:mysql配置里-和_等价的,重启服务后,远程就挂了
其实就是3306端口关闭了
同样本地通过tcp/ip这种sock一样也进不去了
只能本地走文件socket才能进去
然后言归正传,进行口令修改
刷新一下,再修改就行了,