第3节. 函数存储过程和触发器和用户管理

函数-例1

创建函数

image-20230526134652185

查看函数列表

image-20230526141610376

image-20230526141933726

函数是保存在mysql.proc表中的

image-20230526142241519

排版换一下

image-20230526142306722

删除函数

image-20230526142546221

函数-例2

image-20230526142833301

上图的注意点:改变以往;分号作为一个命令去断句执行的行为。而//才是断句。

然后最后结尾又改回去了,所以DELIMITER是一个全局命令。类似交换机的user-interface里的screen-length

image-20230526143623778

创建函数deleteByid,并传递参数uid,类型是SMALLINT 正数, RETRUNS返回的是字符串

BEGIN和END是标明函数体,如果简单的一句话搞定就不用写BEGIN和END,但是多句就不行了。

对比,跑函数之前的students里的行数是21

image-20230526150224757

image-20230526150424810

跑一下函数后的行数是

image-20230526150401407

第10行没了

image-20230526150447030

函数里 赋值的方法①:set a =x 👇

image-20230526152343782

注意

END// DELIMITER; 其实是错误的写法,它表示已“END // DELIMITER;”结束的,而不是以//结束。

image-20230526153120382

image-20230526154124496

函数里赋值方法②: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 ;

image-20230526155908985

👆DECLARE申明看来要放在函数体的最前面,紧跟着BEGIN才行。

存储过程,更似shell里的函数

调用的时候比上面的讲的函数更像shell里的函数。

image-20230601180453125

IN是给存储过程找个函数功能传递参数,是传进去

OUT是传出来

INOUT是双向的。

存储过程的案例

create创建、call执行 存储过程

image-20230601181931136

image-20230601182146782

show procedure status;查看👇

image-20230601182927590

image-20230601191633464

image-20230601191932747

image-20230601191944372

注意对比函数的type

image-20230601192047360

mysql库里也是存放了很多重要信息的:比如用户账号、还这里看到myql.proc里的函数、存储过程。

image-20230601192249208

所以备份一定是要备份的。

存储过程参数的传递

image-20230601192745939

image-20230601192826247

注意如果换一个数据库就会报错,需要指定找个存储过程在哪个库里执行

image-20230601193106588

自定义变量在FUNCTION和PRODECURE里的类型

1、局部变量:var 这种

2、全局变量:@var 这种

image-20230601193902122

理解一下上面的mysql里的脚本,哈哈

image-20230601193956602

变量是会话级别的变量,就是说 退出mysql的当前交互,变量就没了

image-20230601194408215

看下out参数的效果,从函数里传出来给到了全局变量。

image-20230601194757281

上图中的row_count()函数是上一次命令更改了多少行的意思。

image-20230601200014417

本例中就是 select row_count() into num;上一条cli,也就是DELETE xxx 更改了18行。

image-20230601200338027

同样测一下

image-20230601200717202

流程控制--存储过程和函数中可以使用IF CASE这些语句,这些专业叫法叫做“流程控制”

image-20230601202137385

LEAVE相当于break

ITERATE相当于continue

触发器--准确来讲应该叫事件触发器

举例:比如你在jd购买了100个手机,下单了,那么库存里就要去掉100个【手机,所以事件就是下单100个,触发就是库存里自动减去100个。

image-20230601204841697

DEFINER 是以什么身份来执行

TRIGGER就是定义触发器的名称

BEFORE 在 INSERT|UPDATE|DELETE之前进行的动作,换句话说就是在你增、改、删之前触发了某个动作,实际上就是不会去执行增、改、删了。就是说BEFORE就是用自定义的动作来代替trigger_event事件了。

触发器示例

附带主键的定义写法补充

image-20230601205433887

一般是在定义字段的时候 比如 stu_id INT(11) NOT NULL AUTO_INCREMENT PRIMARY KEY,这样后跟一个主键来定义。

也可以单独PRIMARY KEY(stuid)去定义主键,那么这种是一般用来定义复合主键的。

image-20230602175145882

做两个表student_info和student_count两个表供触发器来测试效果,

然后👇做两个触发器:

image-20230602175641891

插入一行记录后再查看

image-20230602181017048

可见触发器生效了,因为触发器就是检测到该表的row数量,insert就是将另一个表student_count +1

image-20230602180948602

插入两行,就是增加2个计数

image-20230602181640014

而删掉一行,就计数减一

image-20230602181922711

image-20230602182141953

image-20230602182458762

触发器trigger是放在information_schema里的triggers表里的。

image-20230606091601382

但是information_schema库 并不是磁盘上的文件,所有在磁盘上以文件形式存在的库👇

image-20230606092013386

information_schema是在内存里,所以理论上在information_schema里的后果就是重启mysql服务后触发器丢失。但是我甚至重启centos后发现触发器还在!说明其实触发器还在其他地方存放

image-20230606093024627

如果将teachers表里的TID=3的那行删掉,那么students表里的TearcherID=3的怎么办?理论上是不让删的,

这个时候就会有一种做法--叫 级联删除,就是上面的teachers表里的删了,下面students里的涉及对应老师的那些行也都删了。

但其实,好多公司规范里是不让用外键和级联的。阿里的JAVA开发手册里有提到👇

image-20230606093939230

image-20230606093928676

用户账号和权限管理

image-20230606100654335

image-20230606100337777

mysql新的版本,password不是放在这里的,可能放在authentication_string里。

image-20230606100501140

image-20230606103116892

image-20230606104700512

删除drop好了

image-20230613092147163

改密码-方法1

看下passwrod函数:加密口令的方法,password()就是加密口令的。

image-20230613092330003

改密码👇

image-20230613092652513

密码必须加密

image-20230613092758965

看个localhost的坑,生产中也是要关闭反向解析的。

先说结论,就是localhost和127.0.0.1不是一回事,举例

现在有两个root,一个是root@localhost,一个是root@127.0.0.1

image-20230613093423419

然后使用root@127.0.0.1这个账号和centos这个密码登入

发现明明是127,结果被反向解析成localhost,然后localhost的密码又不是centos,所以deny了

image-20230613093726796

关闭反向解析,让127.0.0.1回归IP,就可以对上root@127.0.0.1 centos这个账号密码了

image-20230613094003750

然后去配置文件做永久关闭就行了,这里OFF就是做解析了,ON就是不做解析。

skip_name_resolve 是忽略名词解析,ON,就是打开就是忽略的意思。

image-20230613094250935

然后故障就解决了

image-20230613094340216

改密码-老的方法2失灵了

image-20230613095145199

https://stackoverflow.com/questions/64841185/error-1356-hy000-view-mysql-user-references-invalid-tables-or-columns-o

image-20230613095158581

验证很简单啊,之前view也学过,

image-20230613095536234

image-20230613095801130

可以用alert就可以了

image-20230624214440119

忘记root密码-破解

1、最粗暴的方法就是,肯定不能用了

rm -rf /var/lib/mysql/* 这样数据里的所有东西都没了,重启服务后,自动初始化一些必要的库会。

2、正常方法

image-20230624204948159

重启后就可以不用密码了

image-20230624205103176

但是此时远程用户也同样不用输入密码就直接进来了

image-20230624212446213

这就不太好了,这就需要开启维护模式--也就是只能本地连接,远程就无法连接了如下👇

image-20230624212656225

PS:mysql配置里-和_等价的,重启服务后,远程就挂了

image-20230624212802244

其实就是3306端口关闭了

image-20230624212937885

同样本地通过tcp/ip这种sock一样也进不去了

image-20230624213028838

只能本地走文件socket才能进去

image-20230624213126886

然后言归正传,进行口令修改

image-20230624213400696

刷新一下,再修改就行了,

image-20230624214232997

image-20230625112254673

取消授权REVOKE

Copyright 🌹 © oneyearice@126.com 2022 all right reserved,powered by Gitbook文档更新时间: 2024-07-28 14:47:47

results matching ""

    No results matching ""