视图
- 什么是视图
视图就是通过查询得到一张虚拟表,然后保存下来,下次可以直接使用
其实视图也是表
- 为什么要用视图
如果要频繁的操作一张虚拟表(拼表组成的),你就可以制作成视图,后续直接操作
- 如何操作
# 固定语法
create view 表名 as 虚拟表的查询SQL语句
# 具体操作
create view teacher2course as
select * from teacher inner join course
on teacher.id = course.teacher_id;
- 注意
1. 创建视图在硬盘上只会有表结构,没有表数据(数据还是来自于之前的表)
2. 视图一般只用来查询,里面的数据不要继续修改,可能会影响真正的表
- 视图到底使用频率高不高?
不高,当你创建了很多视图之后,会造成表的不好维护
了解即可,基本不用!!!
触发器
在满足对表数据进行增、删、改的情况下,自动触发的功能。
使用触发器可以帮助我们实现监控、日志、自动处理异常等等。
触发器可以在六种情况下自动触发,增前、增后、删前、删后、改前、改后
基本语法结构
create trigger 触发器的名字 before/after insert/update/delete on 表的名字
for each row
begin
SQL语句
end
# 具体使用,针对触发器的名字,我们通常需要做到见名知意
# 针对增
create trigger tri_before_insert_t1 before insert on t1
for each row
begin
SQL语句
end
create trigger tri_after_insert_t1 after insert on t1
for each row
begin
SQL语句
end
# 针对删和针对改,与上述格式一致
ps:修改MySQL默认的语句结束符,只作用于当前窗口
delimiter $$ 将默认的结束符号由;变成$$
delimiter ;
# 案例
create table cmd (
id int primary key auto_increment,
user char(32),
priv char(10),
cmd char(64),
sub_time datetime, # 提交时间
success enum('yes','no') # 0代表执行失败
);
create table errlog(
id int primary key auto_increment,
err_cmd char(64),
err_time datetime
);
# 需求
当cmd表中的记录success字段是no,那么就触发触发器的执行去errlog表中插入数据
# NEW指代的就是一条条数据对象
delimiter $$
create trigger tri_after_insert_cmd after insert on cmd
for each row
begin
if NEW.success = 'no' then
insert into errlog(err_cmd,err_time)
values(NEW.cmd,NEW.sub_time);
end if;
end $$
delimiter ;
# 朝cmd表插入数据
insert into cmd(user,priv,cmd,sub_time,success)
values
('xiao','0123','ls -l /etc',NOW(),'yes'),
('xiao','0123','cat /etc/passwd',NOW(),'no'),
('xiao','0123','useradd xxx',NOW(),'no'),
('xiao','0123','ps aux',NOW(),'yes');
# 模拟日志功能结果
select * from cmd;
+----+------+------+-----------------+---------------------+---------+
| id | user | priv | cmd | sub_time | success |
+----+------+------+-----------------+---------------------+---------+
| 1 | xiao | 0123 | ls -l /etc | 2024-01-29 16:15:31 | yes |
| 2 | xiao | 0123 | cat /etc/passwd | 2024-01-29 16:15:31 | no |
| 3 | xiao | 0123 | useradd xxx | 2024-01-29 16:15:31 | no |
| 4 | xiao | 0123 | ps aux | 2024-01-29 16:15:31 | yes |
+----+------+------+-----------------+---------------------+---------+
select * from errlog;
+----+-----------------+---------------------+
| id | err_cmd | err_time |
+----+-----------------+---------------------+
| 1 | cat /etc/passwd | 2024-01-29 16:15:31 |
| 2 | useradd xxx | 2024-01-29 16:15:31 |
+----+-----------------+---------------------+
# 删除触发器
drop trigger tri_after_insert_cmd;
存储过程
存储过程就类似于python中的自定义函数
它的内部包含了一系列可执行的SQL语句,存储过程存放于MySQL服务端中,你可以直接通过调用存储过程触发内部SQL语句的执行
基本使用
create procedure 存储过程的名字(形参1,形参2,....)
begin
sql代码
end
# 调用
call 存储过程的名字();
三种开发模式
- 第一种
应用程序:程序员写代码开发
MySQL:提前编写好存储过程,供应用程序调用
好处:开发效率提升了,执行效率也上去了
缺点:考虑到人为因素,跨部门沟通的问题,后续的存储过程的扩展性差
- 第二种
应用程序:程序员自己写代码开发之外,涉及到数据库操作也自己动手写
好处:扩展性很高
缺点:开发效率降低,编写SQL语句太过繁琐,而且后续还需要考虑SQL优化的问题
- 第三种
应用程序:只写程序代码,不写SQL语句,基于别人写好的操作MySQL的python的框架直接调用操作即可。
优点:开发效率比上面两种都高
缺点:语句的扩展性差,可能会出现效率低下的问题
总结
第一种基本不用,一般都是第三种,出现效率问题再动手写sql
存储过程具体演示
delimiter $$
create procedure p1(
in m int, # in 表示只进不出,m不能返回出去
in n int,
out res int # out表示该形参可以返回出去
)
begin
select name from teacher where id>m and id<n;
set res=777; # 将res变量修改,用来标识当前的存储过程代码确实执行了
end $$
delimiter ;
call p1(1,2,5); # 报错,ERROR 1414 (42000): OUT or INOUT argument 3 for routine day45.p1 is not a variable or NEW pseudo-variable in BEFORE trigger
# 针对形参res,不能直接传数据,应该先传一个变量名
# 定义变量
set @ret = 10;
# 查看变量对应的值
select @ret;
# 再次调用
call p1(1,2,@ret);
在pymysql模块中如何调用存储过程呢?
import pymysql
conn = pymysql.connect(
host='127.0.0.1',
port=3306,
user='root',
password='111111',
database='day45',
charset='utf8', # 编码千万不要加-
autocommit=True # 自动提交
) # 链接数据库
cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)
# 调用存储过程
cursor.callproc('p1', (1, 2, 5))
"""
@_p1_0=1
@_p1_1=2
@_p1_2=5
"""
print(cursor.fetchall())
cursor.execute('select @_p1_2;')
print(cursor.fetchall()) # [{'@_p1_2': 777}]
函数
跟存储过程是有区别的,存储过程是自定义函数,函数就类似于内置函数。
# 示例:
create table blog(
id int primary key auto_increment,
name char(32),
sub_time datetime
);
insert into blog(name,sub_time)
values
('第1篇','2015-02-01 11:31:22'),
('第2篇','2015-05-06 14:51:12'),
('第3篇','2016-02-01 09:31:53'),
('第4篇','2016-02-01 19:23:45'),
('第5篇','2016-02-01 04:54:14'),
('第6篇','2017-02-01 21:52:56'),
('第7篇','2017-02-01 22:08:32'),
('第8篇','2018-02-01 09:05:32'),
('第9篇','2018-02-01 08:18:22');
select date_format(sub_time,'%Y-%m'),count(id) from blog group by date_format(sub_time,'%Y-%m');
流程控制
# if 判断
delimiter //
create procedure proc_if()
begin
declare i int default 0;
if i = 1 then
select 1;
elseif i = 2 then
select 2;
else
select 7;
end if;
end //
delimiter ;
# while循环
delimiter //
create procedure proc_while()
begin
declare num int;
set num = 0;
while num < 10 do
select
num;
set num = num + 1;
end while;
end //
delimiter ;
标签:insert,触发器,01,create,cmd,视图,time,MySQL
From: https://www.cnblogs.com/xiao01/p/18050502