day49 数据库终章

一、pymysql补充

import pymysql

conn = pymysql.connect(
    host = '127.0.0.1',
    port = 3306,
    user = 'root',
    password = 'root',
    database = 'day46', # 指定我们要编写的库
    charset = 'utf8',# 不能写成utf-8
    autocommit = True # 后面无须确认就可以操作数据库了
) # 链接数据库
cursor = conn.cursor(pymysql.cursors.DictCursor)

# 增
sql = "insert into student values (17,'男',1,'hz')"
rows = cursor.execute(sql)
# rows = cursor.executemany(sql,[(),()....]) # 这条可以一次性添加多个数据,去替换sql中的拼接数据库

conn.commit() # 确认操作
# 改
sql = "update student set sname = 'hhhzzz' where sid = 1"

# 删除
sql = "delete from student where sid = 2"

'''
增改删 涉及到数据的修改,需要进行二次确认
查不需要
'''

二、数据库补充

1 视图(了解)

  • 什么是视图
    • 视图是通过查询得到的一张虚拟表,保存下来
    • 所以,视图其实也是一张表
  • 为什么要有视图
    • 把常用的查询操作保存下来,或者拼表操作,可以减少代码
  • 如何操作
    • create view 视图名(表明) as 虚拟表的查询sql语句

注意事项

'''
1 创建视图在硬盘上只会有表结构,没有表数据(数据来源于原来查询到的表)
2 视图通常只用于查询 不要修改里面的数据
'''
  • 视图使用频率高不高?
    • 不高,创建多了会影响我们判断表与表之间的结构

总结:了解即可,基本不用

2 触发器(了解)

定义:在满足对表数据进行增、删、改情况下,自动触发的功能

作用:使用触发器可以帮助我们实现监控、日志等等

基本语法结构

# 基本语法
cteate trigger 触发器的名字(见名知意) before/after insert/update/delete
 on 表名 for each row 
begin 
    sql语句 
end
'''
2对3 6种情况
增前,增后,删前,删后,改前,改后
'''
# 举例
create trigger tri_after_insert_t1 after insert on t1 
for each row
begin
	sql语句
end

'''
**补充**

修改mysql结束条件

delimiter $$ 表示接下来的mysql操作结束符号为$$ 关闭窗口就改回来了
'''
# 删除触发器

# 案例
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表中的记录succes字段是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
    ('jason','0755','ls -l /etc',NOW(),'yes'),
    ('jason','0755','cat /etc/passwd',NOW(),'no'),
    ('jason','0755','useradd xxx',NOW(),'no'),
    ('jason','0755','ps aux',NOW(),'yes');

# 删除触发器
drop trigger tri_after_insert_cmd;

3 事务

事务为多条sql语句共同执行,只有共同成功和共同失败

事务四大特性:ACID

  • A:原子性
    • 一个事物是一个不可分割的单位,事物中包含着诸多操作,要么同时成功,要么同时失败
  • C:一致性
    • 事物必须是使数据库从一个一致性的状态变到另外一个一致性的状态
    • 一致性和原子性密切相关
  • I:隔离性
    • 一个事物的执行不能被其他事物干扰,并发执行的事物之间也是互不干扰
  • D:持久性/永久性
    • 指一个事物一旦执行成功,那么他对数据库中数据的修改是永久的
    • 接下来的其他操作和故障,不会对他有影响

如何使用事务

# 事务相关的关键字
# 1 开启事务
start transaction;
# 开启事务在确认和回滚之前都属于事务代码
# 2 回滚操作(当事务中间出现一个错误,回到事务执行之前的状态)
rollbake
# 3 确认(确认之后就没法回滚了)
commit

4 存储过程(了解)

存储过程类似于python中的自定义函数

基本使用

create procedure 存储过程的名字(形参1,形参2。。。)
begin 
	sql语句
end

# 调用
call 存储过程的名字();
  

三种开发模型

  • 第一种
    • 应用程序:程序员写代码开发
    • MySQL:提前写好存储过程,供应程序调用
    • 优点:开发效率,执行效率都提高
    • 缺点:需要考虑沟通问题,存储过程扩展性差
  • 第二种
    • 应用程序,MySQL:都是程序员写
    • 优点:扩展性高
    • 缺点:开发效率低,sql语句很繁琐,还要考虑优化
  • 第三种
    • 应用程序:只写代码,用别人写好的操作MySQL的python框架直接操作
    • 优点:开发效率最高
    • 缺点:语句的可扩展性差,可能会出现效率低下的问题

总结:第一种基本不会出现,基本都是第三种,出现效率问题就自己写sql

存储过程mysql演示

delimiter $$
create procedure p1(
	in m int,  # 只进不出  m不能返回出去
    in n int,  
    out res int  # 该形参可以返回出去
    # in所对应的变量时供我们下面sql语句使用的,out对应的变量相当于一个标识,这个变量修改了,表示我们执行了存储过程
)
begin
	select tname from teacher where tid>m and tid<n;
    set res=666;  # 将res变量修改 用来标识当前的存储过程代码确实执行了
end $$
delimiter ;

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

python中的mysql储存过程

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())

5 函数

函数和存储过程是对应的,存储过程就是自定义函数,函数就类似于内置函数

简单举例:如果我们想对当前时间存储,可以自己手打,也可以使用NOW()

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

6 流程控制

就是mysql版本的if多分支和while判断

# 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 ;

7 索引

索引就是一种数据结构,类似于书的目录

比如我们去看字典,有很多种找这个字的办法

  • 找拼音
  • 找偏旁
  • 或者我们提前知道了页码直接翻过去
  • 或者一页一页找

这些不同的去书中找字的办法就是索引,在计算机上就是用不同办法去硬盘中找数据,这就是索引,不同的索引给了我们对不同应用场景的需求实现

在mysql中,索引就是一种‘键’,是存储引擎用于快速找到记录的一种数据结构

  • primary key (主键)
  • unique key (uni键)
  • index key

注意:foreign key不是用来加速查询的,只是用来建立表与表之间关系的

上面三中key,前两种不仅可以加速查询,还有约束条件,比如主键是非空且唯一,uni键是唯一的,index只是用来加速查询的

本质

索引是为了让我们缩小想找数据的范围,减少搜索时间,提高效率,也就是如果我们记录下了一条索引,以后在继续找这条数据的时候就会非常的快

一张表可以有多个索引

索引虽然能给我们在搜索特定数据的时候变的非常快速,但是也有缺点

  • 当表中有大量数据的时候,创建索引会非常慢
    • 因为索引的创建本质上需要用最原始的方法去搜索数据,索引是排除了其他错误路线直接帮我们找到数据
  • 在索引创建完毕后,搜索性能提高了,写的性能降低了
    • 因为在索引创建完毕后,对表的结构也定死了,如果我们要添加数据,相当于破坏了表数据的排列,索引就必须重新创建

8 b+树

把从用户到数据看做是一棵树,用户是树根,找到树叶上的数据需要经历多次对数据路径的判断,每个枝条放的是虚拟数据,用来帮我们区分数据在哪个分支上。

在分支上的数据,相当于一个个索引,他告诉我们这个分支派生出去的子分支哪里可能有我们的数据。所以我们用id字段作为索引,因为id是int类型,相比与其他类型他能在分支上存储的越多。

总结:当分支上的数据越多,说明在一个分支上对数据路径分析越详细,我们就可以通过越少的分支得到数据。走的路越少,我们得到数据的速度就越快

9 聚集索引(primary key)

聚集索引指的就是主键
Innodb 只有两个文件 直接将主键存放在了idb表中
MyIsam 三个文件 单独将索引存在一个文件

10 辅助索引(unique,index)

我们查询的时候不是一直用id(主键),也可能用到其他字段,这个时候就要用到辅助索引,我们从辅助索引到最后去拿到主键找到真正的数据

  • 覆盖索引
    • 如果我们在辅助索引的中途就找到了数据就直接返回结果了
    • select name from user where name='jason';
  • 非覆盖索引
    • 还是需要用到主键
    • select age from user where name='jason';
posted @ 2020-05-08 14:28  lxttt521  阅读(148)  评论(0编辑  收藏  举报