Vista detallada del contenido de hoy
(entender)
什么是视图
视图就是通过查询得到一张虚拟表,然后保存下来,下次可以直接使用
其实视图也是表
为什么要用视图
如果要频繁的操作一张虚拟表(拼表),你就可以制作成视图,后续直接操作
如何操作
固定语法:create view 表名 as 虚拟表的查询语句
具体操作
create view emp666 as
select * from emp1 inner join dep on emp1.dep_id = dep.id
注意
1 创建视图在硬盘上只会有表结构,没有表数据,数据并没有存在硬盘(数据还是来自之前的表)
2 视图一般只用来查询,里面的数据不要进行修改,可能会影响真正的表
视图到底使用频率高不高
使用频率不高
当你创建了很多视图之后,会造成表的不好维护
结论:视图了解即可
Trigger (entender)
在满足对表数据进行增,删,改的情况下,自动触发的功能
使用触发器可以帮助我们实现监控,日志,自动处理异常等等...
触发器可以在6种情况下自动触发 增前增后 删前删后 改前改后
基本语法结构
create trigger 触发器的名字 before/after insert/update/delete 表名
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
针对删除和修改 书写格式一致
修改mysql默认的语句结束符 只作用于当前窗口(临时生效)
delimiter $$ 将默认的结束符号由;改为$$
delimiter ; 重新改回;
案例
需求:当cmd表中的记录succes字段是no那么就触发触发器去执行errlog表中插入的数据
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") # no代表执行失败
);
create table errlog(
id int primary key auto_increment,
err_cmd char(64),
err_time datetime
);
# 创建触发器
delimiter $$
create trigger tri_after_insert_cmd after insert on cmd
for each row
begin
if new.success = "no" then # new指代的就是一条条数据对象
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("nana","0755","is -1 /etc",now(),"yes"),
("nana","0755","cat /etc/password",now(),"no"),
("nana","0755","useradd xxx",now(),"no");
select * from cmd;
select * from errlog;
删除触发器
drop trigger tri_after_insert_cmd;
Asuntos (dominio)
什么是事务
开启一个事务可以包含多条sql语句 这些sql语句要么同时成功
要么一个都别想成功 称之为事务的原子性
事务的作用
保证了对数据操作的安全性
ez:还钱的例子
ez用银行卡给我的支付宝转账1000
1 将ez银行卡的数据减1000块
2 将ez支付宝账户的数据增加1000块
你在操作多条数据的时候可能会出现某几条操作不成功的情况
事务的四大特性
ACID
A:原子性
一个事务是一个不可分隔的单位,事务中包含的诸多操作,要么同时成功,要么同时失败
C:一致性
事务必须是使数据库从一个一致性的状态变到另外一个一致性的状态
一致性跟原子性是密切相关的
I:隔离性
一个事务的执行不能被其他事务干扰
即一个事务内部的操作及使用到的数据对并发的其他事务是隔离的,并发执行的事务之间
也是互不干扰的 (可以理解成快照操作)
D:持久性
也叫"永久性"
一个事务一旦提交成功执行成功,那么它对数据库中的数据的修改应该是永久的
接下来的其他操作或者故障不应该对其有任何的影响
事务三种开启方式
隐式==自动
显式==手动
mysql默认是自动提交事务,使用pymysql操作数据库默认是隐式事务
1. 自动提交事务(隐式开启,隐式提交)
update user set name="baba" where id = 1;
2. 显示事务(显示开启,显示提交)
start transaction; # 开启事务的方式(开启事务后一定要在结尾commit,否则就相当于一直在操作快照,而不是真正的事务)
update user set name="baba" where id = 1;
commit; # 一旦确认就无法回滚操作了
3. 隐式事务(影藏开启,显式提交)
set session autocommit = 0; -- 0是关闭,1是开启;session是设置当前会话变量,global是设置全局变量
如何使用事务
事务相关的关键字
1 开启事务
start transaction; 或者begin; # 开启事务的方式(开启事务后一定要在结尾commit,否则就相当于一直在操作快照,而不是真正的事务)
2 回滚(回到事务执行之前的状态)
rollback; # 例如在转账相关操作涉及到数据安全的时候,出现了异常,可以通过回滚操作回到事务执行之前的状态
3 确认(确认之后无法回滚了)
commit;
开启事务后,commit或者rollback事务都结束
案例:
模拟转账功能
create table user1(
id int primary key auto_increment,
name char(16),
balance int
);
insert into user1(name,balance) values
("nana",1000),
("dada",1000),
("tank",1000);
# 1 先开启事务
start transaction;
# 2 多条sql语句
update user1 set balance=900 where name ="tank";
update user1 set balance=1050 where name ="nana";
update user1 set balance=1050 where name ="dada";
commit; 确认(确认之后就无法回滚了)
rollback; 回滚(回到之前的状态)
总结:
当你想让多条sql语句保持一致性,要么同时成功,要么同时失败
你就应该考虑使用事务
Procedimiento almacenado (entender)
存储过程就类似于python中的自定义函数
它的内部包含了一系列可以执行的sql语句,存储过程存放于mysql服务端中,你可以
直接通过调用存储过程触发内部sql语句的执行
基本使用
create procedure 存储过程的名字(形参1,形参2...)
begin
sql代码
end
# 调用
call存储过程的名字(形参1,形参2...);
三种开发模型
第一种
应用程序:程序员写代码开发
mysql:提前编写好存储过程,供程序员调用
好处:开发效率提升了,执行效率也上去了
缺点:考虑到人为因素,跨部门沟通问题 后续的存储过程的扩展性差
第二种
应用程序:程序员写代码开发之外 设计到数据库操作也自己动手写
优点:扩展性很高
缺点:
开发效率降低
编写sql语句太过繁琐 而却后续还需要考虑sql优化的问题
第三种
应用程序开发:只写程序代码 不写sql语句 基于别人写好的操作mysql的python框架
直接调用操作即可 ORM框架
优点:开发效率比上面两种情况都要高
缺点:语句的扩展性差 可能会出现效率低下的问题
第一种基本不用,一般都是第三种,出现效率问题再动手写sql
存储过程具体演示
delimiter $$
create procedure p1(
in m int, # in只进不出 m不能返回出去
in n int,
out res int # 该形参可以返回出去
)
begin
select name from dep where id>m and id<n;
set res= 666; # 将res变量修改,用来标识当前的存储过程代码确实执行了
end $$
delimiter ;
# 针对形参res 不能直接传数据,应该传一个变量名
# 定义变量
set @ret=10;
# 查看变量对应的值
select @ret;
# 调用并传参
call p1(1,5,@ret);
# 再次查看变量对应的值
select @ret; # @ret的值变成了666
在pymysq模块中如何让调用存储过程代码演示
import pymysql
conn = pymysql.connect(
host="127.0.0.1",
port=3306,
user="root",
password="123",
db="db1",
charset="utf8",
autocommit=True
)
cursor = conn.cursor(pymysql.cursors.DictCursor)
# 调用存储过程
cursor.callproc("p1", (1, 5, 10))
"""
调用存储过程实际上是给代码做了一个变形
@_p1_0=1
@_p1_0=5
@_p1_0=10
"""
print(cursor.fetchall())
cursor.execute("select @_p1_2;")
print(cursor.fetchall()) # [{
'@_p1_2': 666}]
Función (entender)
跟存储过程时与区别的,存储过程时自定义函数,函数就类似于内置函数
比如:NOW()直接获取当前时间
("nana","0755","is -1 /etc",NOW(),"yes")
date_format日期格式的拼接
create table blog (
id int primary key auto_increment,
name char (32),
sub_time datetime
);
insert into blog (name, sub_time)
values
('1','2015-03-01 11:31:21'),
('2','2015-03-11 16:31:21'),
('3','2016-07-01 10:21:31'),
('4','2016-07-22 09:23:21'),
('5','2016-07-23 10:11:11'),
('6','2016-07-25 11:21:31'),
('7','2017-03-01 15:33:21'),
('8','2017-03-01 17:32:21'),
('9','2017-03-01 18:31:21');
#3. 提取sub_time字段的值,按照格式后的结果即"年月"来分组
select date_format(sub_time,"%Y-%m"),count(id) from blog group by
date_format(sub_time,"%Y-%m");
Control de proceso (entender)
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 # 如果num小于10,do表示进入循环
select
num ;
set num = num + 1 ;
end while ;
end //
delimiter ;