进击のpython

*****

数据库——MySQL内置方法


视图

视图是一个虚拟表(非真实存在),其本质是【根据SQL语句获取动态的数据集,并为其命名】

用户使用时只需使用【名称】即可获取结果集,可以将该结果集当做表来使

使用视图我们可以把查询过程中的临时表摘出来,用视图去实现

这样以后再想操作该临时表的数据时就无需重写复杂的sql了,直接去视图中查找即可

但视图有明显地效率问题,并且视图是存放在数据库中的,如果我们程序中使用的sql过分依赖数据库中的视图

即强耦合,那就意味着扩展sql极为不便,因此并不推荐使用

mysql> select * from course;
+-----+--------+------------+
| cid | cname | teacher_id |
+-----+--------+------------+
| 1 | 生物 | 1 |
| 2 | 物理 | 2 |
| 3 | 体育 | 3 |
| 4 | 美术 | 2 |
+-----+--------+------------+
4 rows in set (0.00 sec) mysql> select * from teacher;
+-----+-----------------+
| tid | tname |
+-----+-----------------+
| 1 | 张磊老师 |
| 2 | 李平老师 |
| 3 | 刘海燕老师 |
| 4 | 朱云海老师 |
| 5 | 李杰老师 |
+-----+-----------------+
5 rows in set (0.00 sec) #查询李平老师教授的课程名
mysql> select cname from course where teacher_id = (select tid from teacher where tname='李平老师');
+--------+
| cname |
+--------+
| 物理 |
| 美术 |
+--------+
2 rows in set (0.00 sec)

李平老师的课程名是不是出来一张表,但是这个表我以前说过,这是假的,只是给你看的,不是真实存在的

也就意味着我想用这个表是不可以的,那我要是想用就用到了视图:

增加

#语法:CREATE VIEW 视图名称 AS  SQL语句
create view teacher_view as select tid from teacher where tname='李平老师';
#于是查询李平老师教授的课程名的sql可以改写为
mysql> select cname from course where teacher_id = (select tid from teacher_view);
+--------+
| cname |
+--------+
| 物理 |
| 美术 |
+--------+
rows in set (0.00 sec)

!!!注意注意注意:

  1. 使用视图以后就无需每次都重写子查询的sql,但是这么效率并不高,还不如我们写子查询的效率高
  2. 而且有一个致命的问题:视图是存放到数据库里的,如果我们程序中的sql过分依赖于数据库中存放的视图,那么意味着,一旦sql需要修改且涉及到视图的部分,则必须去数据库中进行修改,而通常在公司中数据库有专门的DBA负责,你要想完成修改,必须付出大量的沟通成本DBA可能才会帮你完成修改,极其地不方便
#修改视图,原始表也跟着改
mysql> select * from course;
+-----+--------+------------+
| cid | cname | teacher_id |
+-----+--------+------------+
| 1 | 生物 | 1 |
| 2 | 物理 | 2 |
| 3 | 体育 | 3 |
| 4 | 美术 | 2 |
+-----+--------+------------+
rows in set (0.00 sec) mysql> create view course_view as select * from course; #创建表course的视图
Query OK, 0 rows affected (0.52 sec) mysql> select * from course_view;
+-----+--------+------------+
| cid | cname | teacher_id |
+-----+--------+------------+
| 1 | 生物 | 1 |
| 2 | 物理 | 2 |
| 3 | 体育 | 3 |
| 4 | 美术 | 2 |
+-----+--------+------------+
rows in set (0.00 sec) mysql> update course_view set cname='xxx'; #更新视图中的数据
Query OK, 4 rows affected (0.04 sec)
Rows matched: 4 Changed: 4 Warnings: 0 mysql> insert into course_view values(5,'yyy',2); #往视图中插入数据
Query OK, 1 row affected (0.03 sec) mysql> select * from course; #发现原始表的记录也跟着修改了
+-----+-------+------------+
| cid | cname | teacher_id |
+-----+-------+------------+
| 1 | xxx | 1 |
| 2 | xxx | 2 |
| 3 | xxx | 3 |
| 4 | xxx | 2 |
| 5 | yyy | 2 |
+-----+-------+------------+
rows in set (0.00 sec)

而且我们不应该修改视图中的记录,而且在涉及多个表的情况下是根本无法修改视图中的记录的

修改

语法:ALTER VIEW 视图名称 AS SQL语句
mysql> alter view teacher_view as select * from course where cid>3;
Query OK, 0 rows affected (0.04 sec) mysql> select * from teacher_view;
+-----+-------+------------+
| cid | cname | teacher_id |
+-----+-------+------------+
| 4 | xxx | 2 |
| 5 | yyy | 2 |
+-----+-------+------------+
rows in set (0.00 sec)

删除

语法:DROP VIEW 视图名称

DROP VIEW teacher_view

触发器

触发器,就是一碰就执行的意思

使用触发器可以定制用户对表进行【增、删、改】操作时前后的行为,注意:没有查询

创建

# 插入前
CREATE TRIGGER tri_before_insert_tb1 BEFORE INSERT ON tb1 FOR EACH ROW
BEGIN
...
END # 插入后
CREATE TRIGGER tri_after_insert_tb1 AFTER INSERT ON tb1 FOR EACH ROW
BEGIN
...
END # 删除前
CREATE TRIGGER tri_before_delete_tb1 BEFORE DELETE ON tb1 FOR EACH ROW
BEGIN
...
END # 删除后
CREATE TRIGGER tri_after_delete_tb1 AFTER DELETE ON tb1 FOR EACH ROW
BEGIN
...
END # 更新前
CREATE TRIGGER tri_before_update_tb1 BEFORE UPDATE ON tb1 FOR EACH ROW
BEGIN
...
END # 更新后
CREATE TRIGGER tri_after_update_tb1 AFTER UPDATE ON tb1 FOR EACH ROW
BEGIN
...
END

使用

#准备表
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
); #创建触发器
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中插入记录,触发触发器,根据IF的条件决定是否插入错误日志
INSERT INTO cmd (
USER,
priv,
cmd,
sub_time,
success
)
VALUES
('egon','0755','ls -l /etc',NOW(),'yes'),
('egon','0755','cat /etc/passwd',NOW(),'no'),
('egon','0755','useradd xxx',NOW(),'no'),
('egon','0755','ps aux',NOW(),'yes'); #查询错误日志,发现有两条
mysql> select * from errlog;
+----+-----------------+---------------------+
| id | err_cmd | err_time |
+----+-----------------+---------------------+
| 1 | cat /etc/passwd | 2017-09-14 22:18:48 |
| 2 | useradd xxx | 2017-09-14 22:18:48 |
+----+-----------------+---------------------+
rows in set (0.00 sec)

①刚开始规定\结尾,最后要还原成;

②创建触发器一定记得分号

③new表示即将插进去的数据,old表示即将要删掉的数据

删除

drop trigger tri_after_insert_cmd;

存储过程

mysql一直在做一件事,力求让应用层面的开发和数据库层面的开发解耦开

所以在数据库层面处理过的数据本质上还是拿给应用层面使用

那就需要一种方法,可以将输入的sql语句封装起来,然后发给应用层

而这就是存储过程,就相当于你是用内置方法写好后用存储过程封装

(那其实跟函数很像,但是他不叫函数哦)

无参

delimiter //
create procedure p1()
BEGIN
select * from blog;
INSERT into blog(name,sub_time) values("xxx",now());
END //
delimiter ;

那这存储过程写好了怎么用呢?

在MySQL是这么用的:

#在mysql中调用
call p1()

在pymysql是这么用的:

#在python中基于pymysql调用
cursor.callproc('p1')
print(cursor.fetchall())

有参

mysql的有参存储过程里面的参数不像python那么自由

他需要定义参数的类型,以及要明确他是传入还是传出的参数

对于存储过程,可以接收参数,其参数有三类:

in 仅用于传入参数用

delimiter //
create procedure p2(
in n1 int,
in n2 int
)
BEGIN select * from blog where id > n1;
END //
delimiter ; #在mysql中调用
call p2(3,2) #在python中基于pymysql调用
cursor.callproc('p2',(3,2))
print(cursor.fetchall()) in:传入参数

out 仅用于返回值用

delimiter //
create procedure p3(
in n1 int,
out res int
)
BEGIN
select * from blog where id > n1;
set res = 1;
END //
delimiter ; #在mysql中调用
set @res=0; #0代表假(执行失败),1代表真(执行成功)
call p3(3,@res);
select @res; #在python中基于pymysql调用
cursor.callproc('p3',(3,0)) #0相当于set @res=0
print(cursor.fetchall()) #查询select的查询结果 cursor.execute('select @_p3_0,@_p3_1;') #@p3_0代表第一个参数,@p3_1代表第二个参数,即返回值
print(cursor.fetchall()) out:返回值

inout 既可以传入又可以当作返回值

delimiter //
create procedure p4(
inout n1 int
)
BEGIN
select * from blog where id > n1;
set n1 = 1;
END //
delimiter ; #在mysql中调用
set @x=3;
call p4(@x);
select @x; #在python中基于pymysql调用
cursor.callproc('p4',(3,))
print(cursor.fetchall()) #查询select的查询结果 cursor.execute('select @_p4_0;')
print(cursor.fetchall()) inout:既可以传入又可以返回

事务

事务用于将某些操作的多个SQL作为原子性操作

一旦有某一个出现错误,即可回滚到原来的状态,从而保证数据库数据完整性

create table user(
id int primary key auto_increment,
name char(32),
balance int
); insert into user(name,balance)
values
('wsb',1000),
('egon',1000),
('ysb',1000); #原子操作
start transaction;
update user set balance=900 where name='wsb'; #买支付100元
update user set balance=1010 where name='egon'; #中介拿走10元
update user set balance=1090 where name='ysb'; #卖家拿到90元
commit; #出现异常,回滚到初始状态
start transaction;
update user set balance=900 where name='wsb'; #买支付100元
update user set balance=1010 where name='egon'; #中介拿走10元
uppdate user set balance=1090 where name='ysb'; #卖家拿到90元,出现异常没有拿到
rollback;
commit;
mysql> select * from user;
+----+------+---------+
| id | name | balance |
+----+------+---------+
| 1 | wsb | 1000 |
| 2 | egon | 1000 |
| 3 | ysb | 1000 |
+----+------+---------+
rows in set (0.00 sec)

这是事务所要达到的效果,那真正的事务是怎么建的呢?

其实你也可以想到,事物的回滚就有点像捕捉错误异常,当捕捉到错误异常,就进行回滚操作

那什么时候执行回滚呢?是不是就应该是程序执行到错误才回滚,你正确执行还会滚个毛线

所以这伪代码就出来了~

delimiter //
create procedure p4(out status int)
BEGIN
1.声明如果出现异常则执行{
set status = 1;
rollback;
}
开始事务
...
commit;
结束
set status = 2;
END//
delimter ;

代码实现

基于上面的伪代码,现在实现一个真正的事务:

delimiter //
create procedure p4(out p5_return_code int)
BEGIN
DECLARE exit handler for sqlexception
BEGIN
set p5_return_code = 1;
rollback;
END;
DECLARE exit handler for sqlwarning
BEGIN
set p5_return_code = 2;
rollback;
END;
START TRANSACTION;
DELETE from tb1;
insert into blog(name,sub_time) values('yyy',now());
commit;
set p5_return_code = 0;
END//
delimter ;

这就写好了一个封装在存储过程中的事务~


*****
*****

数据库(十三):MySQL内置方法的更多相关文章

  1. MySQL内置方法

    distinct(去重) select distinct 字段 from 表名 select distinct age from employee; 四则运算 对筛选的结果进行四则运算 select ...

  2. mysql六:mysql内置功能(视图、触发器、事务、存储过程、函数)

    一.视图 视图是一个虚拟表(非真实存在),其本质是[根据SQL语句获取动态的数据集,并为其命名],用户使用时只需使用[名称]即可获取结果集,可以将该结果集当做表来使用. 通过使用视图可以把查询过程中的 ...

  3. MySQL:记录的增删改查、单表查询、约束条件、多表查询、连表、子查询、pymysql模块、MySQL内置功能

    数据操作 插入数据(记录): 用insert: 补充:插入查询结果: insert into 表名(字段1,字段2,...字段n) select (字段1,字段2,...字段n) where ...; ...

  4. MySQL内置函数

    MySQL中的内置系统函数 用在SELECT语句,以及字句where  order by   having 中UPDTE   DELETE 函数中可以将字段名作为变量来用,变量的值就是这个列对应的每一 ...

  5. python-day4装饰器、生成器、迭代器、内置方法、序列化、软件目录

    @生成器generator a=(i*2 for i in range(10)) a.__next__()#等同于next(a),基本都不用,多用for循环a.send(m)#将m传为yield的值 ...

  6. Python之路(第二十六篇) 面向对象进阶:内置方法

    一.__getattribute__ object.__getattribute__(self, name) 无条件被调用,通过实例访问属性.如果class中定义了__getattr__(),则__g ...

  7. mysql 内置功能 存储过程介绍

    存储过程介绍 就是mysql内置功能把逻辑写好 的功能给封装好,封装成一个接口名,把接口名丢给应用程序,应用程序直接调用接口名实现一系列增删改查功能 这个接口叫存储过程 基于存储过程封装成一个功能 存 ...

  8. python面向对象之反射和内置方法

    一.静态方法(staticmethod)和类方法(classmethod) 类方法:有个默认参数cls,并且可以直接用类名去调用,可以与类属性交互(也就是可以使用类属性) 静态方法:让类里的方法直接被 ...

  9. Python内置方法详解

    1. 字符串内置方法详解 为何要有字符串?相对于元组.列表等,对于唯一类型的定义,字符串具有最简单的形式. 字符串往往以变量接收,变量名. 可以查看所有的字符串的内置方法,如: 1> count ...

随机推荐

  1. 状态机模式 与 ajax 的结合运用

    太神奇了,昨晚做了个梦,梦中我悟出一个道理:凡是涉及到异步操作而且需要返回值的函数,一定要封装成 Promise 的形式,假如返回值取决于多个异步操作的结果,那么需要对每个异步操作进行状态的设计,而且 ...

  2. Spring Cloud Alibaba系列(五)sentinel实现服务限流降级

    一.sentinel是什么 sentinel的官方名称叫分布式系统的流量防卫兵.Sentinel 以流量为切入点,从流量控制.熔断降级.系统负载保护等多个维度保护服务的稳定性.在Spring Clou ...

  3. Python之浅谈多态和封装

    目录 组合 什么是组合 为什么使用组合 多态和多态性 多态 什么是多态? 多态性 好处 多态性 什么是多态性 封装 封装是什么意思? 隐藏 如何用代码实现隐藏 python 实际上是可以访问隐藏属性的 ...

  4. I/O模式及select、 poll、 epoll

    I/O多路复用技术 复用技术(multiplexing)并不是新技术而是一种设计思想,在通信和硬件设计中存在频分复用.时分复用.波分复用.码分复用等.在日常生活中复用的场景也非常多.从本质上来说,复用 ...

  5. Angular2-------Error: Unexpected value ‘undefined’ declared by the module ‘模块名

    请检查[app.module.ts]文件中的[declarations]模块最后是否多了一个逗号 (完)

  6. JAVA基础-继承机制

    需要掌握的知识点: 包的使用 继承时,子类如何覆盖父类方法(重写和重载) 继承时,构造方法的执行过程 JVM中子类如何实例化(先实例化父,再实例化子) super和this关键字 final关键字 包 ...

  7. A Simple Problem,题解

    题目: 分析: 看到式子,推一推其实就是(y+x)*(y-x)=n,显然可以根号n的枚举,判断一下合不合法直接出结果,然后就是代码.注意x!=0. #include <cstdio> #i ...

  8. Traffic Real Time Query System 圆方树+LCA

    题目描述 City C is really a nightmare of all drivers for its traffic jams. To solve the traffic problem, ...

  9. 我终于弄懂了Python的装饰器(二)

    此系列文档: 1. 我终于弄懂了Python的装饰器(一) 2. 我终于弄懂了Python的装饰器(二) 3. 我终于弄懂了Python的装饰器(三) 4. 我终于弄懂了Python的装饰器(四) 二 ...

  10. day03 编程语言介绍

    一.编程语言分类 目录 一.编程语言分类 1.低级语言 1.1机器语言 1.2.汇编语言 2.高级语言 2.1编译型语言(例:c语言) 2.2解释型语言(例:世界上最好的语言python) 3总结 二 ...