疫情环境下的网络学习笔记 python 5.8 数据库入门终章

5.8

昨日回顾

  1. navicat

  2. 涉及多表查询的时候,肯定用到联表操作和子查询,可以联很多次

  3. 把昨天上课的题目理解自己写出来

  4. pymysql模块

    import pymysql
    conn = pymysql.connect(
    	host = '127.0.0.1',
    	port = 3306,
    	user = root,
    	password = '6008',
    	database = 'db1', # 可以简写成db
    	charset = 'utf8'
    )
    # cursor = conn.cursor() # 括号内不急啊参数,查询得到的是元组形式,数据不够明确
    cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)
    sql = 'select * from user'
    res = cursor.execute(sql) # 返回值是sql语句执行受影响的行数
    cursor.fetchone() # 拿到一条数据,数据本身
    cursor.fetchall() # 拿到所有的结果,列表
    # 这个cursor对象有类似文件指针的东西
    cursor.scroll(1,'absolute')
    
  5. sql注入

    有很多种方式,我们用最明显的方式

    日常应用应该在获取用户输入的内容时候,限制一些特殊符号的输入

    在pymysql中,execute嫩帮你过滤,在sql中用%s占位,在execute里拼接

  6. pymysql补充

    # 增删改查
    sql = 'insert into user(name,password) values(%s,%s)'
    rows = cursor.execute(sql)
    # 增删改查都有结果,但是无法直接执行这个命令
    # 要sql语句起作用,要进行二次确认
    conn.commit()
    # 确认操作,才能在sql中产生影响
    # 也可以在conn中设置autocmmit为True,不用commit也能增删改
    
    # 同时进行多次增删改:executemany
    # 执行多个sql语句:列表套元组
    executemany(sql,[(123,123),(123,123)])
    

今日内容

今日内容基本都是了解知识点,基本用不到

  1. 视图
  2. 触发器
  3. 事务(掌握)
  4. 存储过程
  5. 内置函数
  6. 流程控制
  7. 索引理论

视图

  • 什么是视图

    视图就是通过查询一张虚拟表,保存下来,下次可以直接使用

# 创建视图
create view 表名 as 表查询的sql语句
# 创建的视图在navicat的视图里可以查看
# 生成的视图在硬盘上只存一个frm文件:表结构,数据还在原来的表中
# 视图一般只用来查询,不要改,改了会报错

# 删除视图
DROP VIEW teacher_view;

创建过多视图维护会有麻烦,所以不要创建过多的视图

触发器

在满足对表数据进行增,删,改的情况下,自动触发的功能,使用触发器可以帮助我们实现监控,日志,自动处理异常等等

触发器可以在六种情况下自动触发:增前,增后,删前删后,改前改后

# 触发器语法
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
# 在t1表增加数据之前触发
# 针对删除和修改的书写一致

为了让触发器 begin和end之间的sql语句能正常执行,不因为使用分号就结束,修改结束sql语句的符号:delimiter

# 修改mysql语句的结束符:将;分号改成别的
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
);

# 创建触发器,把sql语句结束符号变为 //
# 因为sql语句是在触发后运行的,所以还是用分号
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');
    
# 可以通过
select * from errlog # 看到错误记录
# 删除触发器
drop trigger tri_after_insert_cmd;

事务

  • 什么是事务

    开启一个可以包含多条sql语句,这些sql语句要么同时成功,要么一个都不成功,称之为事物的原子性

  • 事务的作用

    保证对数据操作的安全性:操作多条数据的时候,可能出现一条不成功的情况

  • 事物的四大特性

    ACID
    A:原子性:一个事物是一个不可分割的单位,事务中包含的诸多操作要么同时成功要么同时失败
    C:一致性:事务必须是数据库
    I:隔离性
    D:持久性
    
  • 使用方法

    # 事务相关的关键字
    # 1 开启事务
    start transaction;
    # 2 回滚(回到事务执行之前的状态)
    rollback;
    # 3 确认(确认之后就无法回滚了)
    commit;
    
    """模拟转账功能"""
    create table user(
    	id int primary key auto_increment,
        name char(16),
        balance int
    );
    insert into user(name,balance) values
    ('jason',1000),
    ('egon',1000),
    ('tank',1000);
    
    
    # 1 先开启事务
    start transaction;
    # 2 多条sql语句
    update user set balance=900 where name='jason';
    update user set balance=1010 where name='egon';
    update user set balance=1090 where name='tank';
    
    # 出现异常,回滚到初始状态
    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;
    
  • 总结

    • 当你想让多条sql语句保持一致性,使用事务

存储过程

类似于python中的自定义函数,存储过程存放于mysql服务端中,直接调用存储过程触发内部sql语句的执行

演示

create procedure 存储过程的名字(形参1,形参2,...)
begin
	sql代码
end
# 调用
call 存储过程的名字();

三种开发模式

  1. 第一种

    应用程序:程序员写代码开发,MySQL提前写好存储过程,给应用程序调用

    优点:不需要写sql语句了,提升开发效率

    缺点:考虑到人为因素,跨部门沟通的问题,后续的存储过程扩展性差

  2. 第二种

    程序员写代码开发之外,涉及到数据库的操作也自己写

    优点:扩展性高

    缺点:开发效率低,编写sql太繁琐,后续还要考虑优化问题

  3. 第三种

    应用程序开发只写程序代码,不写sql语句,基于别人写好的mysql框架,直接调用操作即可

    ORM框架

    优点:效率最高

    缺点:扩展性差,效率低

第一种基本不用,一般都是第三种,出现问题再手动写sql

存储过程具体

delimiter $$
create procedure p1(
	in m int,  # 只进不出  m不能返回出去
    in n int,
    out res int  # 该形参可以返回出去
)
begin
	select tname from teacher where tid>m and tid<n;
    set res=666;  # 将res变量修改 用来标识当前的存储过程代码确实执行了
end $$
delimiter ;

# 针对形参res 不能直接传数据 应该传一个变量名
# 定义变量
set @ret = 10;
# 查看变量对应的值
select @ret;delimiter $$
create procedure p1(
	in m int,
	in n int,
	out res int,
)
begin
	select tname from teacher where tid>m and tid<n;
	set res=0 # 修改res,标识当前存储过程确实执行了
end	$$
delimiter ;

# 针对形参res,不能直接传值,应该传一个变量名
# 定义变量
set @ret = 10;
# 查看变量对应的值
select @ret;

在python中调用存储过程

import pymysql


conn = pymysql.connect(
    host = '127.0.0.1',
    port = 3306,
    user = 'root',
    passwd = '123456',
    db = 'day48',
    charset = 'utf8',
    autocommit = True
)
cursor = conn.cursor(pymysql.cursors.DictCursor)
# 调用存储过程
cursor.callproc('p1',(1,5,10))
"""
@_p1_0=1
@_p1_1=5
@_p1_2=10
"""
# print(cursor.fetchall())
cursor.execute('select @_p1_2;')
print(cursor.fetchall())

函数

跟存储过程是有区别的,存储过程是自定义函数,函数就类似于是内置函数

('jason','0755','ls -l /etc',NOW(),'yes')

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');

select date_format(sub_time,'%Y-%m'),count(id) from blog group by date_format(sub_time,'%Y-%m');

流程控制

# if 判断
# while 循环

索引

一种数据结构,类似于书的目录,以后在查询数据应该先找目录再找数据,而不是一页一页的翻书,提升查询速度降低IO

索引再MySQL中也叫键,是存储引擎用于快速查找记录的一种数据结构

  • primary key
  • unique key
  • index key

上面三种key,前面两种除了可以增加查询速度意外还各自有约束条件,而最后一种index key 没有任何约束,只是用来帮助快速查询

本质

通过不断地缩小想要的数据范围,筛选出最终的结果,同时将随机事件一页一页地翻,变成顺序事件(先找目录,再找数据)

有了索引机制,我们可以总是用一种固定的方式查找数据

一张表中可以有多个索引(多个目录),但是索引太多会导致索引很慢

b+树

只有叶子节点存放的是真实的数据,其他节点存放的是虚拟数据

树的层级越高,经历的步骤就越多

聚集索引

聚集索引指的就是主键

innodb只有两个文件,直接将主键存放在idb表中

辅助索引

主键之外的都叫辅助索引,查询索引不会一致用到主键,也可能用到username,password一类字段,那么这个时候没有办法利用聚集索引,这个时候你就可以根据情况给其他字段设置辅助索引,也是一个b+树

覆盖索引

在辅助索引的叶子节点就已经拿到了需要的数据

原文地址:https://www.cnblogs.com/telecasterfanclub/p/12855970.html