zoukankan      html  css  js  c++  java
  • 疫情环境下的网络学习笔记 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+树

    覆盖索引

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

  • 相关阅读:
    使用Mutex实现程序单实例运行(c#)
    KMP(转载来自Matrix67原创)
    【转载】搞ACM的你伤不起(转载,不过这个神作实在是太经典了)
    POJ 3125 Printer Queue【打印队列】
    弱校ACM奋斗史
    POJ 2063 Investment
    程序员的艺术:排序算法舞蹈【视频】
    POJ 2063 Investment【经典完全背包】
    快速幂模板
    搞ACM的你伤不起(转载,不过这个神作实在是太经典了)
  • 原文地址:https://www.cnblogs.com/telecasterfanclub/p/12855970.html
Copyright © 2011-2022 走看看