课程安排(day44)

数据库基础

前端基础

django基础

bbs小作业

路飞学城 django drf

linux

go

k8s docker

爬虫

cmdb

代码发布

每日测验

今日暂无

数据库

存储数据的演变过程

  • 随意的存到一个文件中、数据格式也是千差万别的完全取决于我们自己

    """
    # 小李
    jason|123|NB
    # 小王
    egon-123-DBJ
    # 小红
    tank~123~hecha
    """
    
  • 软件开发目录规范

    限制了存储数据的具体位置

    """
    bin
    conf
    core
    db
    lib
    readme
    """
    

    假设上述是一个单机游戏

    那么每个人的游戏记录只会在自己的计算机上面保存

    注册登录的账号也只能在自己的计算机上有效

  • 如何将单机变成连网

    """
    将数据库保存部分全部统一起来
    所有人操作数据都来一个地方操作
    """
    

数据库的本质

"""
本质其实就是一款基于网络通信的应用程序
那其实每个人都可以开发一款数据库软件 因为它仅仅就是一个基于网络通信的应用程序也就意味着数据库软件其实有很多很多关系型数据库MySQL、oracle、db2、access、sql server非关系型数据库redis、mongodb、memcache
"""
# 关系型1 数据之间彼此有关系或者约束男生表和前女友表2 存储数据的表现形式通常是以表格存储 name     password       hobbyjason    123           学习egon    123           女教练tank   123           吃生蚝每个字段还会有存储类型的限制比如姓名只能存字符串...
# 非关系型存储数据通常都是以k,v键值对的形式

MySQL

"""
任何基于网络通信的应用程序底层用的都是socket-服务端-基于socket通信-收发消息-SQL语句-客户端-基于socket通信-收发消息-SQL语句
"""
MySQL不单单支持MySQL自己的客户端app还支持其他编程语言来充当客户端操作如何解决语言沟通的障碍?# 1 让服务端兼容所有的语言(一个人精通多国语言)# 2 采用统一的语言(SQL语句)

重要概念介绍

"""
库           》》》          文件夹
表           》》》          文件
记录         》》》          文件内一行行的数据name     password      hobbyjason    123           学习egon    123           女教练tank   123           吃生蚝
表头              表格的第一行字段
字段              name、password、hobby
"""

MySQL的安装

"""
在IT界 一般都不会轻易的使用最新版本的软件,因为新版本可能会出现各种问题
(你原本项目跑的好好的 非要画蛇添足更新版本 然后项目奔溃)
小段子:更新完没事 那么你还是一个普通员工更新完出事 那么你就是一名"烈士"
"""
# MySQL有很多版本(5.6、5.7、8.0) 目前企业里面用的比较多的还是5.6左右

参考网站:https://www.mysql.com/

下载5.6版本即可,如果你下载了其他版本问题也不大,因为sql语句是一样的学

按照教学方式下载,会将服务端和客户端一并下载到本地

为了学习方便我们将服务端和客户端都在本地启动,后期到了公司服务端会专门跑在一台服务器上,所有人基于网络连接服务端操作

MySQL服务端与客户端

"""
服务端
mysqld.exe客户端
mysql.exe
"""

注意

"""
在前期配置MySQL的时候 cmd终端尽量以管理员的身份运行windows+r 输入cmd  进入的是普通用户终端 有一些命令是无法执行的
搜索cmd右键 以管理员身份运行
"""

启动

  • 先切换到mysqld所在的bin目录下,然后输入mysqld即可

  • 保留原来的cmd窗口重新打开一个

    """
    常见软件的默认端口号MySQL  3306redis  6379mongodb 27017django  8000flask   5000...MySQL第一次以管理员身份进入是没有密码的 直接回车即可客户端连接服务端完整命令mysql -h 127.0.0.1 -P 3306 -uroot -p
    """
    

sql语句初识

"""
1 MySQL中的sql语句是以分号作为结束的标志2 基本命令show databases;  查看所有的库名3 连接服务端的命令可以简写mysql -h 127.0.0.1 -P 3306 -uroot -pmysql -uroot -p4 当你输入的命令不对 又不想让服务端执行并返回报错信息 可以用\c取消错误命令 5 客户端退出  退出命令加不加分号都可以执行quitexit6 当你在连接服务端的时候 发现只输入mysql也能连接但是你不是管理员身份 而只是一个游客模式
"""

环境变量配置及系统服务制作

小知识点补充

"""
1 如何查看当前具体进程tasklisttasklist |findstr mysqld2 如何杀死具体进程(只有在管理员cmd窗口下才能成功)taskkill /F /PID PID号
"""

环境变量配置

"""
每次启动mysqld需要先切到对应的文件路径下才能操作太多繁琐
将mysqld所在的文件路径添加到系统环境变量中
"""

还是繁琐 需要起两个cmd窗口 不好

将mysql服务端制作成系统服务(开机自启动)

"""
查看当前计算机的运行进程数services.msc将mysql制作成系统服务mysqld --install
移除mysql系统服务mysqld --remove
"""

设置密码

"""
mysqladmin -uroot -p原密码 password 新密码
改命令直接在终端输入即可 无序进入客户端mysqladmin -uroot -p123 password 123456
"""

破解密码

出去玩了好几个月,回来返现密码忘了,死活进不去

"""
你可以将mysql获取用户名和密码校验的功能看成是一个装饰器
装饰在了客户端请求访问的功能上我们如果将该装饰器移除 那么mysql服务端就不会校验用户名和密码了
"""
# 1 先关闭当前mysql服务端命令行的方式启动(让mysql跳过用户名密码验证功能)mysqld --skip-grant-tables
# 2 直接以无密码的方式连接mysql -uroot -p   直接回车
# 3 修改当前用户的密码update mysql.user set password=password(123456) where         user='root' and host='localhost';
"""
真正存储用户表的密码字段 存储的肯定是密文
只有用户自己知道明文是什么 其他人都不知道 这样更加的安全
密码比对也只能比对密文
"""
# 4 立刻将修改数据刷到硬盘flush privileges;
# 5 关闭当前服务端 然后以正常校验授权表的形式启动

统一编码

  • mysql默认的配置文件

    """
    my-default.ini
    ini结尾的一般都是配置文件程序启动会先加载配置文件中的配置之后才真正的启动
    """
    [mysqld]  # 一旦服务端启动立刻加载下面的配置
    sql_mode=NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES
    [mysql]  # 一旦客户端启动立刻加载下面的配置
    ...
    [client]  # 其他客户端
    ...# 需要你自己新建一个my.ini的配置文件# 验证配置是否真的是自动加载
    [mysql]
    print('hello world')# 修改配置文件后一定要重启服务才能生效# 统一编码的配置 无需掌握 直接拷贝即可# 偷懒 将管理员的用户名和密码也添加到配置文件中
    [mysqld]
    character-set-server=utf8
    collation-server=utf8_general_ci
    [client]
    default-character-set=utf8
    [mysql]
    user="root"
    password=123456
    default-character-set=utf8
    

基本sql语句

PS:大部分程序的业务逻辑其实都是增删改查

"""
辛辛苦苦一个月 只为了一条sql语句(将自己账户的钱修改一下)
"""

针对库的增删改查(文件夹)

# 增
create database db1;
create database db2 charset='gbk';
# 查
show databases;  # 查所有
show create database db1;  # 查单个
# 改
alter database db2 charset='utf8';
# 删
drop database db2;

针对表的增删改查(文件)

"""
在操作表(文件)的时候 需要指定所在的库(文件夹)
"""
# 查看当前所在的库的名字
select database();
# 切换库
use db1; # 增
create table t1(id int,name char(4));
# 查
show tables;  # 查看当前库下面所有的表名
show create table t1;
describe t1;  # 支持简写 desc t1;
# 改
alter table t1 modify name char(16);
# 删
drop table t1;"""
create table db2.t1(id int);  也可以用绝对路径的形式操作不同的库
"""

针对数据的增删改查(一行行数据)

"""
一定要先有库 有表 最后才能操作记录
"""
# 增
insert into t1 values(1,'jason');
insert into t1 values(1,'jason'),(2,'egon'),(3,'tank');
# 查
select * from t1;  # 该命令当数据量特别大的时候不建议使用
select name from t1;
# 改
update t1 set name='DSB' where id > 1;
# 删
delete from t1 where id > 1;
delete from t1 where name='jason';
# 将表所有的数据清空
delete from t1;

作业布置

  • 每个人自己完成MySQL的安装
  • 整理今日内容
  • 今天介绍的所有命令都给我记下来尤其是数据的操作命令
  • 复习巩固之前的知识点

每日测验(day45)

  • 简述数据库的本质及分类
  • MySQL中针对库、表、数据的增删改查语句

上周内容回顾

  • 存储数据的演变过程

    """
    1 随意建文件、数据格式也是千差万别的jason|123egon~123tank+1232 软件开发目录规范明确了数据存放的大致位置3 从单机变成联网 如何操作数据统一存放并且格式固定将原本存放于本地的数据全部存放到某一个基于网络通信的地方然后所有的客户端都去该地方统一的操作数据
    """
    
  • 数据库的概念

    """
    本质其实就是一款基于网络通信的应用程序也就意味着数据库软件你也可以自己开发
    还意味着市面上的数据库软件很多
    """
    关系型MySQL、oracle、access、SQL server、sqlite
    非关系型redis、mongodb(最像关系型数据库的非关系型数据库)、memcache关系型数据彼此之间有约束或者联系存储数据一般都是以表格形式
    非关系型通常以K、V键值对的形式存储数据
    
  • MySQL简介

    """
    本质其实就是一款基于网络通信的应用程序
    MySQL开源免费
    企业使用率较广
    使用方便 好学
    """
    
  • SQL语句

    """
    服务端
    客户端
    MySQL支持多中类型的客户端1.自己写的客户端2.其他编程语言写(python、java、php...)如何兼容1.本人牛逼 自动区分对应语言2.统一标准(******)
    """
    
  • 重要概念

    """
    库        文件夹
    表        文件
    记录      文件内一行行的数据表头     表格第一行字段
    字段      字段名+字段类型
    """
    
  • MySQL的安装

    """
    1 版本问题IT界一般情况下不会直接使用最新版本的软件(如果你在使用某一些模块或者软件的时候出现了未知的错误 确实无法解决,那么这个时候应该考虑是否是模块或者软件兼容性问题)我们以5.6版本为例(市面上用的最多的版本)python解释器推荐你们使用3.6版本 其他版本针对一些模块还存在兼容性问题2 官网安装即可(每个人都要自己独立的安装完成)
    """
    
  • MySQL主要文件介绍

    """
    bin文件下的两个启动程序
    mysqld  服务端
    mysql   客户端
    """
    mysqld先启动服务端
    之后客户端连接mysql -h ... -P ... -uroot -p简写mysql -uroot -p第一次连接不需要密码 直接回车即可当你值属于mysql发现也可以连接服务端但是这个时候是游客模式
    
  • 初识sql语句

    """
    sql语句是以分号作为结束的标志 ;取消书写的内容执行\c查看所有的库名
    show databases;退出服务端quitexit
    """
    
  • 环境变量及系统服务配置

    """
    环境变量将bin目录路径添加到系统环境变量即可制作系统服务的时候cmd一定要用管理员身份运行mysqld --installmysqld --remove
    """
    
  • 修改密码

    mysqladmin -uroot -p原密码 password新密码
    # 直接在cmd输入即可 无需进入服务端
    
  • 忘记密码(了解)

    """
    1 跳过授权表的形式启动服务端mysqld --skip-grant-tables
    2 直接无密码登录管理员账户mysql -uroot -p
    3 重置当前用户的密码update mysql.user set password=password(123) where user='root' and host='localhost';flush privileges;
    4 再以正常的方式启动服务端
    """
    
  • 配置文件

    """
    MySQL的配置文件 在启动的时候都会自动去加载对应的配置\s  发现编码不一致
    """
    [mysql]
    ...
    [mysqld]
    ...
    [client]
    ...编码配置无需掌握 直接拷贝使用即可
    
  • 基本SQL语句

    其实我们程序员写的本质就是数据的增删改查,没什么高大上的东西

    """针对库的增删改查"""
    create database db1;show databases;
    show create database db1;alter database db1 charset='gbk';drop database db1;"""针对表的增删改查"""
    # 如何查看当前所在的库
    select database();
    # 切换当前所在的库
    use db1;create table t1(id int,name char);show tables;
    show create table t1;
    desc t1;  >>>: 全称 describe t1;alter table t1 modify name char(16);drop table t1;"""针对记录的增删改查"""
    # 先明确 要有库和表 才能操作记录
    insert into t1 values(1,'jason'),(2,'egon');select * from t1;
    select name from t1;update t1 set name='DSB' where name='egon';delete from t1;
    delete from t1 where id > 1;
    

今日内容概要

  • 存储引擎

  • 数据类型

    整型

    浮点型

    字符类型

    日期类型

    枚举与集合类型

  • 约束条件

今日内容详细

存储引擎

日常生活中文件格式有很多中,并且针对不同的文件格式会有对应不同存储方式和处理机制(txt,pdf,word,mp4…)

针对不同的数据应该有对应的不同的处理机制来存储

存储引擎就是不同的处理机制

MySQL主要存储引擎

  • Innodb

    是MySQL5.5版本及之后默认的存储引擎

    存储数据更加的安全

  • myisam

    是MySQL5.5版本之前默认的存储引擎

    速度要比Innodb更快 但是我们更加注重的是数据的安全

  • memory

    内存引擎(数据全部存放在内存中) 断电数据丢失

  • blackhole

    无论存什么,都立刻消失(黑洞)

"""
# 查看所有的存储引擎
show engines;# 不同的存储引擎在存储表的时候 异同点
create table t1(id int) engine=innodb;
create table t2(id int) engine=myisam;
create table t3(id int) engine=blackhole;
create table t4(id int) engine=memory;# 存数据
insert into t1 values(1);
insert into t2 values(1);
insert into t3 values(1);
insert into t4 values(1);
"""

创建表的完整语法

# 语法
create table 表名(字段名1 类型(宽度) 约束条件,字段名2 类型(宽度) 约束条件,字段名3 类型(宽度) 约束条件
)# 注意
1 在同一张表中字段名不能重复
2 宽度和约束条件是可选的(可写可不写) 而字段名和字段类型是必须的约束条件写的话 也支持写多个字段名1 类型(宽度) 约束条件1 约束条件2...,create table t5(id);  报错
3 最后一行不能有逗号create table t6(id int,name char,);   报错"""补充"""
# 宽度一般情况下指的是对存储数据的限制create table t7(name char);  默认宽度是1insert into t7 values('jason');insert into t7 values(null);  关键字NULL针对不同的版本会出现不同的效果5.6版本默认没有开启严格模式 规定只能存一个字符你给了多个字符,那么我会自动帮你截取5.7版本及以上或者开启了严格模式 那么规定只能存几个 就不能超,一旦超出范围立刻报错 Data too long for ....
"""严格模式到底开不开呢?"""
MySQL5.7之后的版本默认都是开启严格模式的
使用数据库的准则:能尽量少的让数据库干活就尽量少 不要给数据库增加额外的压力# 约束条件 null  not null不能插入null
create table t8(id int,name char not null);"""
宽度和约束条件到底是什么关系宽度是用来限制数据的存储约束条件是在宽度的基础之上增加的额外的约束
"""

基本数据类型

整型

  • 分类

    TINYINT SMALLINT MEDUIMINT INT BIGINT

  • 作用

    存储年龄、等级、id、号码等等

"""
以TINYINT 是否有符号默认情况下是带符号的超出会如何超出限制只存最大可接受值
"""
create table t9(id tinyint);
insert into t9 values(-129),(256);# 约束条件之unsigned 无符号
create table t10(id tinyint unsigned);create table t11(id int);
# int默认也是带符号的
# 整型默认情况下都是带有符号的# 针对整型 括号内的宽度到底是干嘛的
create table t12(id int(8));
insert into t12 values(123456789);"""
特例:只有整型括号里面的数字不是表示限制位数
id int(8)如果数字没有超出8位 那么默认用空格填充至8位如果数字超出了8位 那么有几位就存几位(但是还是要遵守最大范围)
"""
create table t13(id int(8) unsigned zerofill);
# 用0填充至8位# 总结:
针对整型字段 括号内无需指定宽度 因为它默认的宽度以及足够显示所有的数据了

严格模式

# 如何查看严格模式
show variables like "%mode";模糊匹配/查询关键字 like%:匹配任意多个字符_:匹配任意单个字符# 修改严格模式set session  只在当前窗口有效set global   全局有效set global sql_mode = 'STRICT_TRANS_TABLES';修改完之后 重新进入服务端即可

浮点型

  • 分类

    FLOAT、DOUBLE、DECIMAL

  • 作用

    身高、体重、薪资

    # 存储限制
    float(255,30)  # 总共255位 小数部分占30位
    double(255,30)  # 总共255位 小数部分占30位
    decimal(65,30)  # 总共65位 小数部分占30位# 精确度验证
    create table t15(id float(255,30));
    create table t16(id double(255,30));
    create table t17(id decimal(65,30));
    """你们在前期不要给我用反向键 所有的命令全部手敲!!!增加熟练度"""insert into t15 values(1.111111111111111111111111111111);
    insert into t16 values(1.111111111111111111111111111111);
    insert into t17 values(1.111111111111111111111111111111);float < double < decimal
    # 要结合实际应用场景 三者都能使用
    

字符类型

  • 分类

    """
    char定长char(4)    数据超过四个字符直接报错 不够四个字符空格补全
    varchar变长varchar(4)  数据超过四个字符直接报错 不够有几个存几个
    """
    create table t18(name char(4));
    create table t19(name varchar(4));insert into t18 values('a');
    insert into t19 values('a');# 介绍一个小方法 char_length统计字段长度
    select char_length(name) from t18;
    select char_length(name) from t19;
    """
    首先可以肯定的是 char硬盘上存的绝对是真正的数据 带有空格的
    但是在显示的时候MySQL会自动将多余的空格剔除
    """# 再次修改sql_mode 让MySQL不要做自动剔除操作
    set global sql_mode = 'STRICT_TRANS_TABLES,PAD_CHAR_TO_FULL_LENGTH';
    

    char与varchar对比

    """
    char缺点:浪费空间优点:存取都很简单直接按照固定的字符存取数据即可jason egon alex wusir tank 存按照五个字符存 取也直接按照五个字符取varchar优点:节省空间缺点:存取较为麻烦1bytes+jason 1bytes+egon 1bytes+alex 1bytes+tank 存的时候需要制作报头取的时候也需要先读取报头 之后才能读取真实数据以前基本上都是用的char 其实现在用varchar的也挺多
    """补充:进来公司之后你完全不需要考虑字段类型和字段名因为产品经理给你发的邮件上已经全部指明了
    

时间类型

  • 分类

    date:年月日 2020-5-4

    datetime:年月日时分秒 2020-5-4 11:11:11

    time:时分秒11:11:11

    Year:2020

    create table student(id int,name varchar(16),born_year year,birth date,study_time time,reg_time datetime
    );
    insert into student values(1,'egon','1880','1880-11-11','11:11:11','2020-11-11 11:11:11');
    

枚举与集合类型

  • 分类

    """
    枚举(enum)  多选一
    集合(set)   多选多
    """
    
  • 具体使用

    create table user(id int,name char(16),gender enum('male','female','others')
    );
    insert into user values(1,'jason','male');  正常
    insert into user values(2,'egon','xxxxooo');  报错
    # 枚举字段 后期在存数据的时候只能从枚举里面选择一个存储 create table teacher(id int,name char(16),gender enum('male','female','others'),hobby set('read','DBJ','hecha')
    );
    insert into teacher values(1,'jason','male','read');  正常
    insert into teacher values(2,'egon','female','DBJ,hecha');  正常
    insert into teacher values(3,'tank','others','生蚝'); 报错
    # 集合可以只写一个  但是不能写没有列举的
    

    总结

    """
    字段类型
    严格模式约束条件not nullzerofillunsigned
    """
    

作业

  • 整理今日内容到笔记
  • 设计的所有命令全部用手敲一遍,不要使用方向键

每日测验(day46)

  • 你都了解哪些MySQL存储引擎,简单说说它们的特点
  • 创建表的完整语法及注意事项
  • MySQL基本数据类型有哪些

昨日内容回顾

  • 存储引擎

    """
    针对不同的数据应该有不同的处理机制查看MySQL所有的存储引擎
    show engines;InnodbMySQL5.5版本之后默认的存储引擎支持事务 行锁 外键    数据更加的安全创建表会生成两个文件表结构文件表数据文件
    MyIsamMySQL5.5版本之前的默认的存储引擎它虽然在数据安全上没有Innodb可靠 但是查询速度上较Innodb更快创建表会生成三个文件表结构文件表数据文件表索引文件
    memory内存引擎临时数据存储 创建表会生成一个文件表结构文件
    blackhole黑洞创建表会生成一个文件表结构文件
    """
    
  • 创建表的完整语法

    # 语法
    create table 表名(字段名1 字段类型(宽度) 约束条件,字段名2 字段类型(宽度) 约束条件,字段名3 字段类型(宽度) 约束条件
    )
    # 注意
    1 在同一张表中字段名不能重复
    2 宽度和约束条件是可选的 字段名和字段类型是必须的
    3 最后一个字段后面不能加逗号# 宽度一般情况下是对存储数据的限制
    # 约束条件可以有多个 是额外的限制
    
  • 严格模式

    # 使用数据库的时候 应该尽量让数据库少干活!!!show variables like '%mode';set session
    set global sql_mode = 'STRICT_TRANS_TABLES';
    
  • 基本数据类型

    """
    整型TINYINT INT BIGINT默认都是有符号的int(4)针对整型括号内的数字并不是用来限制存储的不够四位默认用空格填充够四位有几位存几位 zerofill总结 以后在定义整型字段的时候 其实都不需要自己加宽度因为整型都自带宽度 完全足够展示所有的数字浮点型float(255,30)double(255,30)decimal(65,30)只要是浮点型 括号后面有两个数字第一个数字表示的总位数第二个数字表示的小数位精确度float < double < decimal扩展:其实在实际生产中 很多看似需要用整型或者浮点型存储的数据内部可能都是用的字符类型存储字符类型char(4)  定长只能存储最大四个字符 超出报错 不超默认用空格补全varchar(4)  变长只能存储最大四个字符 超出报错 不超有几个存几个char Vs varcharchar浪费空间存取方便 简单暴力 直接按照固定的位数存取即可varchar节省空间但是相较于char 它的存取速度较慢因为它在存取数据的时候需要有一个 报头以前用char很多 限制varchar很多时间类型date  年月日datetime  年月日时分秒time  时分秒year  年(有范围限制)枚举与集合类型枚举enum多选一  集合set多选多(也可以单选)gender enum('male','female','others')hobby set('read','sangna','DBJ','hecha')你的数据只能来源于字段提供的选择项 不能凭空捏造
    """
    
  • 约束条件

    """
    zerofill
    unsigned
    not null
    """
    

今日内容概要

  • 约束条件
  • 表与表之间建关系(约束)(重点)
  • 修改表的完整语法大全
  • 复制表
  • 作业布置(如何判断表关系及如何建立表关系)

今日内容详细

约束条件

default默认值

# 补充知识点  插入数据的时候可以指定字段
create table t1(id int,name char(16)
);
insert into t1(name,id) values('jason',1);create table t2(id int,name char(16),gender enum('male','female','others') default 'male'
);
insert into t2(id,name) values(1,'jason');
insert into t2 values(2,'egon','female');

unique唯一

# 单列唯一
create table t3(id int unique,name char(16)
);
insert into t3 values(1,'jason'),(1,'egon');
insert into t3 values(1,'jason'),(2,'egon');# 联合唯一
"""
ip和port
单个都可以重复 但是加载一起必须是唯一的
"""
create table t4(id int,ip char(16),port int,unique(ip,port)
);
insert into t4 values(1,'127.0.0.1',8080);
insert into t4 values(2,'127.0.0.1',8081);
insert into t4 values(3,'127.0.0.2',8080);
insert into t4 values(4,'127.0.0.1',8080);  报错

primary key主键

"""
1.单单从约束效果上来看primary key等价于not null + unique
非空且唯一!!!
"""
create table t5(id int primary key);
insert into t5 values(null);  报错
insert into t5 values(1),(1);  报错
insert into t5 values(1),(2); """
2.它除了有约束效果之外 它还是Innodb存储引擎组织数据的依据
Innodb存储引擎在创建表的时候必须要有primary key
因为它类似于书的目录 能够帮助提示查询效率并且也是建表的依据
"""
# 1 一张表中有且只有一个主键 如果你没有设置主键 那么会从上往下搜索直到遇到一个非空且唯一的字段将它自动升级为主键
create table t6(id int,name char(16),age int not null unique,addr char(32) not null unique
);# 2 如果表中没有主键也没有其他任何的非空且唯一字段 那么Innodb会采用自己内部提供的一个隐藏字段作为主键,隐藏意味着你无法使用到它 就无法提示查询速度# 3 一张表中通常都应该有一个主键字段 并且通常将id/uid/sid字段作为主键
# 单个字段主键
create table t5(id int primary keyname char(16)
);
# 联合主键(多个字段联合起来作为表的主键 本质还是一个主键)
create table t7(ip char(16),port int,primary key(ip,port)
);"""
也意味着 以后我们在创建表的时候id字段一定要加primary key
"""

auto_increment自增

# 当编号特别多的时候 人为的去维护太麻烦
create table t8(id int primary key auto_increment,name char(16)
);
insert into t8(name) values('jason'),('egon'),('kevin');# 注意auto_increment通常都是加在主键上的 不能给普通字段加
create table t9(id int primary key auto_increment,name char(16),cid int auto_increment
);
ERROR 1075 (42000): Incorrect table definition; there can be only one auto column and it must be defined as a key

结论

"""
以后在创建表的id(数据的唯一标识id、uid、sid)字段的时候
id int primary key auto_increment
"""

补充

delete from t1  删除表中数据后 主键的自增不会停止truncate t1  清空表数据并且重置主键

表与表之间建关系

"""
定义一张员工表 表中有很多字段
id name gender dep_name dep_desc
"""
# 1 该表的组织结构不是很清晰(可忽视)
# 2 浪费硬盘空间(可忽视)
# 3 数据的扩展性极差(无法忽视的)# 如何优化?
"""上述问题就类似于你将所有的代码都写在了一个py文件中"""
将员工表拆分  员工表和部门表

外键

"""
外键就是用来帮助我们建立表与表之间关系的
foreign key
"""

表关系

"""
表与表之间最多只有四种关系一对多关系在MySQL的关系中没有多对一一说一对多 多对一 都叫一对多!!!多对多关系一对一关系没有关系
"""

一对多关系

"""
判断表与表之间关系的时候 前期不熟悉的情况下 一定要按照我给你的建议
换位思考  分别站在两张表的角度考虑员工表与部门表为例先站在员工表思考一个员工能否对应多个部门(一条员工数据能否对应多条部门数据)不能!!!(不能直接得出结论 一定要两张表都考虑完全)再站在部门表思考一个部门能否对应多个员工(一个部门数据能否对应多条员工数据)能!!!得出结论员工表与部门表示单向的一对多所以表关系就是一对多
"""
foreign key1 一对多表关系   外键字段建在多的一方2 在创建表的时候 一定要先建被关联表 3 在录入数据的时候 也必须先录入被关联表
# SQL语句建立表关系
create table dep(id int primary key auto_increment,dep_name char(16),dep_desc char(32)
);create table emp(id int primary key auto_increment,name char(16),gender enum('male','female','others') default 'male',dep_id int,foreign key(dep_id) references dep(id)
);
insert into dep(dep_name,dep_desc) values('sb教学部','教书育人'),('外交部','多人外交'),('nb技术部','技术能力有限部门');
insert into emp(name,dep_id) values('jason',2),('egon',1),('tank',1),('kevin',3);# 修改dep表里面的id字段
update dep set id=200 where id=2;  不行
# 删除dep表里面的数据
delete from dep;  不行# 1 先删除教学部对应的员工数据 之后再删除部门操作太过繁琐# 2 真正做到数据之间有关系更新就同步更新删除就同步删除
"""
级联更新   >>>   同步更新
级联删除   >>>   同步删除
"""
create table dep(id int primary key auto_increment,dep_name char(16),dep_desc char(32)
);create table emp(id int primary key auto_increment,name char(16),gender enum('male','female','others') default 'male',dep_id int,foreign key(dep_id) references dep(id) on update cascade  # 同步更新on delete cascade  # 同步删除
);
insert into dep(dep_name,dep_desc) values('sb教学部','教书育人'),('外交部','多人外交'),('nb技术部','技术能力有限部门');
insert into emp(name,dep_id) values('jason',2),('egon',1),('tank',1),('kevin',3);

多对多

"""
图书表和作者表
"""
create table book(id int primary key auto_increment,title varchar(32),price int,author_id int,foreign key(author_id) references author(id) on update cascade  # 同步更新on delete cascade  # 同步删除
);
create table author(id int primary key auto_increment,name varchar(32),age int,book_id int,foreign key(book_id) references book(id) on update cascade  # 同步更新on delete cascade  # 同步删除
);
"""
按照上述的方式创建 一个都别想成功!!!
其实我们只是想记录书籍和作者的关系
针对多对多字段表关系 不能在两张原有的表中创建外键
需要你单独再开设一张 专门用来存储两张表数据之间的关系
"""
create table book(id int primary key auto_increment,title varchar(32),price int
);
create table author(id int primary key auto_increment,name varchar(32),age int
);
create table book2author(id int primary key auto_increment,author_id int,book_id int,foreign key(author_id) references author(id) on update cascade  # 同步更新on delete cascade,  # 同步删除foreign key(book_id) references book(id) on update cascade  # 同步更新on delete cascade  # 同步删除
);

一对一

"""
id name age addr phone hobby email........
如果一个表的字段特别多 每次查询又不是所有的字段都能用得到
将表一分为二  用户表用户表id name age用户详情表id addr phone hobby email........站在用户表一个用户能否对应多个用户详情   不能!!!站在详情表一个详情能否属于多个用户      不能!!!结论:单向的一对多都不成立 那么这个时候两者之间的表关系就是一对一或者没有关系(好判断)客户表和学生表在你们报名之前你们是客户端报名之后是学生(期间有一些客户不会报名)
"""一对一 外键字段建在任意一方都可以 但是推荐你建在查询频率比较高的表中
create table authordetail(id int primary key auto_increment,phone int,addr varchar(64)
);
create table author(id int primary key auto_increment,name varchar(32),age int,authordetail_id int unique,foreign key(authordetail_id) references authordetail(id) on update cascade  # 同步更新on delete cascade  # 同步删除
)

总结

"""
表关系的建立需要用到foreign key一对多外键字段建在多的一方多对多自己开设第三张存储一对一建在任意一方都可以 但是推荐你建在查询频率较高的表中判断表之间关系的方式换位思考!!!员工与部门图书与作者作者与作者详情
"""

修改表(了解)

# MySQL对大小写是不敏感的
"""
1 修改表名alter table 表名 rename 新表名;2 增加字段alter table 表名 add 字段名 字段类型(宽度)  约束条件;alter table 表名 add 字段名 字段类型(宽度)  约束条件 first;alter table 表名 add 字段名 字段类型(宽度)  约束条件 after 字段名;3 删除字段alter table 表名 drop 字段名;4 修改字段alter table 表名 modify 字段名 字段类型(宽度) 约束条件;alter table 表名 change 旧字段名 新字段名 字段类型(宽度) 约束条件;"""

复制表(了解)

"""
我们sql语句查询的结果其实也是一张虚拟表
"""
create table 表名 select * from 旧表;  不能复制主键 外键 ...create table new_dep2 select * from dep where id>3;

作业布置

练习:账号信息表,用户组,主机表,主机组

#用户表
create table user(
id int not null unique auto_increment,
username varchar(20) not null,
password varchar(50) not null,
primary key(username,password)
);#用户组表
create table usergroup(
id int primary key auto_increment,
groupname varchar(20) not null unique
);#主机表
create table host(
id int primary key auto_increment,
ip char(15) not null unique default '127.0.0.1'
);#业务线表
create table business(
id int primary key auto_increment,
business varchar(20) not null unique
);#建关系:user与usergroupcreate table user2usergroup(
id int not null unique auto_increment,
user_id int not null,
group_id int not null,
primary key(user_id,group_id),
foreign key(user_id) references user(id),
foreign key(group_id) references usergroup(id)
);#建关系:host与business
create table host2business(
id int not null unique auto_increment,
host_id int not null,
business_id int not null,
primary key(host_id,business_id),
foreign key(host_id) references host(id),
foreign key(business_id) references business(id)
);#建关系:user与host
create table user2host(
id int not null unique auto_increment,
user_id int not null,
host_id int not null,
primary key(user_id,host_id),
foreign key(user_id) references user(id),
foreign key(host_id) references host(id)
);

练习:

# 班级表
cid caption
# 学生表
sid sname gender class_id
# 老师表
tid tname
# 课程表
cid cname   teacher_id
# 成绩表
sid student_id course_id number

最幸福的阶段(day47)

网络并发

数据库(简单)

前端(简单 枯燥)

django(有趣)

慢慢的蜕变(小白慢慢变成程序员)

每日测验

  • 你所知道的约束条件有哪些
  • 表与表之间关系有几种,如何判断
  • 创建上述表关系的SQL语法如何书写

昨日内容回顾

  • 约束条件

    """
    not null
    zerofill
    unsigneddefaultgender enum('male','female','others') default 'male'unique单列唯一id int unique联合唯一ip int,port int,unique(ip,port)primary key  主键1.在限制效果上跟not null + unique一致id int primary key2.它还是Innodb存储引擎组织数据的依据 1.使用Innodb规定一张表中必须有且只有一个主键2.当你没有设置主键的时候1.从上往下查找非空且唯一的自动升级为主键2.如果什么都没有设置 那么就会使用内部隐藏的字段作为主键无法使用到3.一张表中通常都应该有一个id字段并且该字段应该是主键auto_increment自增列该限制条件只能加在被设置成键的字段上 并且一般都是跟主键一起使用id int primary key auto_increment
    """针对主键补充知识点你在将表中数据删除的时候 主键的自增并不会停止 truncate 清空数据并重置主键
    
  • 外键

    """
    外键就是用来在代码层面真正的实现表与表之间的关系
    foreign key
    """
    
  • 表与表之间建关系

    """
    表与表之间的关系只有三种一对多在MySQL中 一对多和多对一 都叫一对多外键字段建在多的那一方多对多关系无需建外键 而是单独开设一张表专门用来存储关系一对一外键字段建在任意一方均可但是推荐你建在查询频率较高的表中
    """
    """判断表关系前期不熟练一定要换位思考 慢慢问自己"""# 一对多判断
    图书与出版社先站在图书表一本书能否被多个出版社出版           版权问题 不可以!!!再站在出版社表一个出版社能否出版多本书         可以结论:单向的一对多成立 那么表关系就是一对多  书是多的一方外键带来的约束1.在创建表的时候一定要先创建被关联表2.在插入数据的时候也要先插入被关联表3.操作数据的时候 会出现多种限制  同步更新 同步删除create table publish(id ...);create table book(id ...publish_id int,foreign key(publish_id) references publish(id)on update cascade  # 同步更新on delete cascade  # 同步删除);# 多对多图书和作者先站在图书表一本书可不可以有多个作者 可以!!!再站在作者表一个作者能不能写多本书      可以!!!结论:图书和作者是双向的一对多 那么表关系就是 多对多一定要单独开设一张新的表存储表关系create table book(id ...)create table author(id ...)create table book2author(id ...book_id int,author_id int,foreign key(book_id) references book(id)on update cascade  # 同步更新on delete cascade,  # 同步删除foreign key(author_id) references author(id)on update cascade  # 同步更新on delete cascade,  # 同步删除)
    # 一对一qq用户表客户与学生表"""当你一张表中的数据并不都是频率需要用到的情况 但是字段有特别的多那么这个时候你就应该考虑分表 然后做一对一的关联节省查询时间和传输时间"""作者与作者详情无论站在哪一方都不能成立一对多双方一对多都不成立那么表关系一对一没有关系create table author(id ...authordetail_id int unique,foreign key(authordetail_id) references authordetail(id)on update cascade  # 同步更新on delete cascade,  # 同步删除);create tabel authordetail(id ...);
    

    补充

    """
    表与表之间如果有关系的话 可以有两种建立联系的方式1.就是通过外键强制性的建立关系2.就是自己通过sql语句逻辑层面上建立关系delete from emp where id=1;delete from dep where id=1;创建外键会消耗一定的资源 并且增加了表与表之间的耦合度在实际项目中 如果表特别多 其实可以不做任何外键处理 直接通过sql语句来建立逻辑层面上的关系到底用不用外键取决于实际项目需求
    """
    
  • 修改表

    """
    alter table t1 rename new_t1;alter table t1 add 字段名 ...;
    alter table t1 add 字段名 ... first;
    alter table t1 add 字段名 ... after 旧字段;alter table t1 drop 字段名;modify一般都是用来修改字段的字段类型 约束条件等 不能修改字段名
    alter table t1 modify 字段名 数据类型(宽度) 约束条件alter table t1 change 旧字段名 新字段名 ...;
    """
    
  • 复制表

    """
    我们sql语句查询出来的结果也可以看成是一张表(虚拟表)
    言外之意 就是针对这个查询结果还可以继续用查询表的语法继续操作该虚拟表
    """
    
  • 作业

    """
    自己联系表关系的判断与创建
    笔记里面给的代码只是一个参考而已
    """
    

今日内容概要

  • 如何查询表

    """
    select
    where
    group by
    having
    distinct
    order by
    limit
    regexp
    like
    ...
    """
    
  • 连表操作理论

今日内容详细

前期表准备

create table emp(id int not null unique auto_increment,name varchar(20) not null,sex enum('male','female') not null default 'male', #大部分是男的age int(3) unsigned not null default 28,hire_date date not null,post varchar(50),post_comment varchar(100),salary double(15,2),office int, #一个部门一个屋子depart_id int
);#插入记录
#三个部门:教学,销售,运营
insert into emp(name,sex,age,hire_date,post,salary,office,depart_id) values
('jason','male',18,'20170301','张江第一帅形象代言',7300.33,401,1), #以下是教学部
('tom','male',78,'20150302','teacher',1000000.31,401,1),
('kevin','male',81,'20130305','teacher',8300,401,1),
('tony','male',73,'20140701','teacher',3500,401,1),
('owen','male',28,'20121101','teacher',2100,401,1),
('jack','female',18,'20110211','teacher',9000,401,1),
('jenny','male',18,'19000301','teacher',30000,401,1),
('sank','male',48,'20101111','teacher',10000,401,1),
('哈哈','female',48,'20150311','sale',3000.13,402,2),#以下是销售部门
('呵呵','female',38,'20101101','sale',2000.35,402,2),
('西西','female',18,'20110312','sale',1000.37,402,2),
('乐乐','female',18,'20160513','sale',3000.29,402,2),
('拉拉','female',28,'20170127','sale',4000.33,402,2),
('僧龙','male',28,'20160311','operation',10000.13,403,3), #以下是运营部门
('程咬金','male',18,'19970312','operation',20000,403,3),
('程咬银','female',18,'20130311','operation',19000,403,3),
('程咬铜','male',18,'20150411','operation',18000,403,3),
('程咬铁','female',18,'20140512','operation',17000,403,3);# 当表字段特别多 展示的时候错乱 可以使用\G分行展示
select * from emp\G;# 个别同学的电脑在插入中文的时候还是会出现乱码或者空白的现象 你可以将字符编码统一设置成GBK

几个重要关键字的执行顺序

# 书写顺序
select id,name from emp where id > 3;
# 执行顺序
from
where
select"""
虽然执行顺序和书写顺序不一致 你在写sql语句的时候可能不知道怎么写
你就按照书写顺序的方式写sqlselect * 先用*号占位之后去补全后面的sql语句最后将*号替换后你想要的具体字段明天会一直使用 这里先理解
"""

where筛选条件

# 作用:是对整体数据的一个筛选操作
# 1.查询id大于等于3小于等于6的数据
select id,name,age from emp where id>=3 and id<=6;
select id,name from emp where id between 3 and 6;  两者等价# 2.查询薪资是20000或者18000或者17000的数据
select * from emp where salary=20000 or salary=18000 or salary=17000;
select * from emp where salary in (20000,18000,17000);# 3.查询员工姓名中包含字母o的员工的姓名和薪资
"""
模糊查询like%  匹配任意多个字符_  匹配任意单个字符
"""
select name,salary from emp where name like '%o%';# 4.查询员工姓名是由四个字符组成的 姓名和薪资  char_length()   _
select name,salary from emp where name like '____';
select name,salary from emp where char_length(name) = 4;# 5.查询id小于3或者id大于6的数据
select * from emp where id not between 3 and 6;# 6.查询薪资不在20000,18000,17000范围的数据
select * from emp where salary not in (20000,18000,17000);# 7.查询岗位描述为空的员工姓名和岗位名  针对null不用等号 用is
select name,post from emp where post_comment = NULL;
select name,post from emp where post_comment is NULL;

group by分组

# 分组实际应用场景  分组应用场景非常的多男女比例部门平均薪资部门秃头率国家之间数据统计# 1 按照部门分组
select * from emp group by post;
"""
分组之后 最小可操作单位应该是组 还不再是组内的单个数据上述命令在你没有设置严格模式的时候是可正常执行的 返回的是分组之后 每个组的第一条数据 但是这不符合分组的规范:分组之后不应该考虑单个数据 而应该以组为操作单位(分组之后 没办法直接获取组内单个数据)如果设置了严格模式 那么上述命令会直接报错
"""
set global sql_mode = 'strict_trans_tables,only_full_group_by';设置严格模式之后  分组 默认只能拿到分组的依据
select post from emp group by post;
按照什么分组就只能拿到分组 其他字段不能直接获取 需要借助于一些方法(聚合函数)"""
什么时候需要分组啊???关键字 每个 平均 最高 最低 聚合函数maxminsumcountavg
"""
# 1.获取每个部门的最高薪资
select post,max(salary) from emp group by post;
select post as '部门',max(salary) as '最高薪资' from emp group by post;
select post '部门',max(salary) '最高薪资' from emp group by post;
# as可以给字段起别名 也可以直接省略不写 但是不推荐 因为省略的话语意不明确 容易错乱# 2.获取每个部门的最低薪资
select post,min(salary) from emp group by post;
# 3.获取每个部门的平均薪资
select post,avg(salary) from emp group by post;
# 4.获取每个部门的工资总和
select post,sum(salary) from emp group by post;
# 5.获取每个部门的人数
select post,count(id) from emp group by post;  # 常用 符合逻辑
select post,count(salary) from emp group by post;
select post,count(age) from emp group by post;
select post,count(post_comment) from emp group by post;  null不行# 6.查询分组之后的部门名称和每个部门下所有的员工姓名
# group_concat不单单可以支持你获取分组之后的其他字段值 还支持拼接操作
select post,group_concat(name) from emp group by post;
select post,group_concat(name,'_DSB') from emp group by post;
select post,group_concat(name,':',salary) from emp group by post;
# concat不分组的时候用
select concat('NAME:',name),concat('SAL:',salary) from emp;# 补充 as语法不单单可以给字段起别名 还可以给表临时起别名
select emp.id,emp.name from emp;
select emp.id,emp.name from emp as t1;   报错
select t1.id,t1.name from emp as t1;# 查询每个人的年薪  12薪
select name,salary*12 from emp;

分组注意事项

# 关键字where和group by同时出现的时候group by必须在where的后面
where先对整体数据进行过滤之后再分组操作
where筛选条件不能使用聚合函数
select id,name,age from emp where max(salary) > 3000;select max(salary) from emp;  # 不分组 默认整体就是一组# 统计各部门年龄在30岁以上的员工平均薪资1 先求所有年龄大于30岁的员工select * from emp where age>30;2 再对结果进行分组select * from emp where age>30 group by post;select post,avg(salary) from emp where age>30 group by post;

having分组之后的筛选条件

"""
having的语法根where是一致的
只不过having是在分组之后进行的过滤操作
即having是可以直接使用聚合函数的
"""
# 统计各部门年龄在30岁以上的员工平均工资并且保留平均薪资大于10000的部门
select post,avg(salary) from emp where age>30 group by posthaving avg(salary) > 10000;

distinct去重

"""
一定要注意 必须是完全一样的数据才可以去重!!!
一定不要将逐渐忽视了 有逐渐存在的情况下 是不可能去重的
[
{'id':1,'name':'jason','age':18},
{'id':2,'name':'jason','age':18},
{'id':3,'name':'egon','age':18}
]
ORM  对象关系映射   让不懂SQL语句的人也能够非常牛逼的操作数据库
表                               类
一条条的数据                      对象
字段对应的值                      对象的属性你再写类 就意味着在创建表
用类生成对象 就意味着再创建数据
对象点属性 就是在获取数据字段对应的值
目的就是减轻python程序员的压力 只需要会python面向对象的知识点就可以操作MySQL
"""
select distinct id,age from emp;
select distinct age from emp;

order by排序

select * from emp order by salary;
select * from emp order by salary asc;
select * from emp order by salary desc;
"""
order by默认是升序  asc 该asc可以省略不写
也可以修改为降序     desc
"""
select * from emp order by age desc,salary asc;
# 先按照age降序排  如果碰到age相同 则再按照salary升序排# 统计各部门年龄在10岁以上的员工平均工资并且保留平均薪资大于1000的部门,然后对平均工资降序排序select post,avg(salary) from emp where age>10 group by posthaving avg(salary) > 1000order by avg(salary) desc;

limit限制展示条数

select * from emp;
"""针对数据过多的情况 我们通常都是做分页处理"""
select * from emp limit 3;  # 只展示三条数据select * from emp limit 0,5;
select * from emp limit 5,5;
第一个参数是起始位置
第二个参数是展示条数

正则

select * from emp where name regexp '^j.*(n|y)$';

多表操作

前期表准备

#建表
create table dep(
id int,
name varchar(20)
);create table emp(
id int primary key auto_increment,
name varchar(20),
sex enum('male','female') not null default 'male',
age int,
dep_id int
);#插入数据
insert into dep values
(200,'技术'),
(201,'人力资源'),
(202,'销售'),
(203,'运营');insert into emp(name,sex,age,dep_id) values
('jason','male',18,200),
('egon','female',48,201),
('kevin','male',18,201),
('nick','male',28,202),
('owen','male',18,203),
('jerry','female',18,204);

表查询

select * from dep,emp;  # 结果   笛卡尔积
"""
了解即可 不知道也没关系
"""select * from emp,dep where emp.dep_id = dep.id;"""
MySQL也知道 你在后面查询数据过程中 肯定会经常用到拼表操作
所以特地给你开设了对应的方法inner join  内连接left join   左连接right join  右连接union        全连接
"""
# inner join  内连接
select * from emp inner join dep on emp.dep_id = dep.id;
# 只拼接两张表中公有的数据部分# left join   左连接
select * from emp left join dep on emp.dep_id = dep.id;
# 左表所有的数据都展示出来 没有对应的项就用NULL# right join  右连接
select * from emp right join dep on emp.dep_id = dep.id;
# 右表所有的数据都展示出来 没有对应的项就用NULL# union      全连接  左右两表所有的数据都展示出来
select * from emp left join dep on emp.dep_id = dep.id
union
select * from emp right join dep on emp.dep_id = dep.id;

子查询

"""
子查询就是我们平时解决问题的思路分步骤解决问题第一步第二步...
将一个查询语句的结果当做另外一个查询语句的条件去用
"""
# 查询部门是技术或者人力资源的员工信息1 先获取部门的id号2 再去员工表里面筛选出对应的员工select id from dep where name='技术' or name = '人力资源';select name from emp where dep_id in (200,201);select * from emp where dep_id in (select id from dep where name='技术' or name = '人力资源');

总结

表的查询结果可以作为其他表的查询条件
也可以通过起别名的方式把它作为一个张虚拟表根其他表关联"""
多表查询就两种方式先拼接表再查询子查询 一步一步来
"""

作业

1.整理今日内容
2.完成下列分组查询练习题(以课上建表代码为参考)1. 查询岗位名以及岗位包含的所有员工名字2. 查询岗位名以及各岗位内包含的员工个数3. 查询公司内男员工和女员工的个数4. 查询岗位名以及各岗位的平均薪资5. 查询岗位名以及各岗位的最高薪资6. 查询岗位名以及各岗位的最低薪资7. 查询男员工与男员工的平均薪资,女员工与女员工的平均薪资
3.练习拼表操作并理解其意义
4.理解子查询思路体会其意义

每日测验(day48)

  • MySQL中常用查询关键字及作用
  • 针对多表查询有哪些查询方式,各自有什么特点

昨日内容回顾

  • 查询主要关键字

    select distinct 字段1,字段2,... from 表名where 分组之前的筛选条件group by  分组条件having  分组之后的筛选条件order by  排序字段1 asc,排序字段2 desclimit 5,5
    
  • where

    where id>=3 and id<=6;
    where id between 3 and 6;where salary=18000 or salary=17000;
    where salary in (18000,17000);
    where salary not in (18000,17000);where salary*20 from emp;# 模糊匹配 like
    """
    %  任意多个字符
    _  任意单个字符
    """
    where name like '%mode%';
    where name like '____';
    where char_length(name) = 4;# 针对null数据 判断的时候用is不要用=
    where post_comment is null;
    
  • group by

    # 分组的应用场景非常多 每个平均最大最小...
    """
    分组之后只能直接获取到分组的依据 其他字段都无法直接获取
    set global sql_mode = 'only_full_group_by'
    """
    select * from emp group by post;  报错
    select post from emp group by post;# group_concat:帮助我们获取到分组之外的字段信息并且可以拼接多个字段
    select post,group_concat(salary,':',name) from emp;
    # concat:分组之前帮助我们获取字段信息并且可以拼接多个字段
    select concat(name,'??') from emp;
    # concat_ws:如果多个字段之间的连接符号是相同的情况下 你可以直接使用concat_ws来完成
    select concat_ws(':',name,age,sex) from emp;
    """
    复习
    '?'.join([111,222,333,444])  报错!
    """# as语法1 可以给展示字段起别名2 可以给表起别名# 聚合函数maxminsumcountavg聚合函数必须在分组之后使用
    
  • having

    # 用法根where一模一样 只不过它是作用于分组之后的再次筛选
    ....group by post having avg(salary) > 30000;
    
  • distinct

    # 数据必须是一模一样的情况下才能去重
    select distinct post from emp;
    
  • order by

    # 排序 默认是升序
    order by salary;  ===   order by salary asc;
    order by salary desc;order by salary asc,age desc;  # 还支持多个字段备用比较
    
  • limit

    """
    限制数据的展示条数    效果就是分页的效果
    """
    select * from emp limit 5;limit 5;
    limit 5,5  第一个参数是起始位置 第二个参数是条数
    
  • regexp

    """
    正则是一门独立的语言
    在python中如果你想使用正则需要借助于re模块面试题1.re模块中常用的方法findall:分组优先展示^j.*(n|y)$不会展示所有正则表达式匹配到的内容而仅仅展示括号内正则表达式匹配到的内容match:从头匹配search:从整体匹配2.贪婪匹配与非贪婪匹配正则表达式默认都是贪婪匹配的将贪婪变成非贪婪只需要在正则表达式后面加?.*  贪婪.*? 非贪婪
    """
    select * from emp where name regexp '^j.*n$'
    
  • 多表查询

    # 联表操作
    select * from emp,dep;  笛卡尔积inner join只拼接两种表中都公有的部分select * from emp inner join dep on emp.dep_id = dep.id;# 要加上表的前缀 不然容易造成冲突 left join左表数据全部展示  没有对应的就用NULL补全right join右表数据全部展示  没有对应的就用NULL补全    union左右全书展示 没有对应的就用NULL补全
    # 子查询
    """
    子查询就是我们平时解决问题的思路 分步处理
    将一张表的查询结果当做另外一条sql语句的查询条件
    (当做条件的时候 用括号括起来)
    select * from emp where id in (select id from dep);
    """
    
  • 总结

    # 书写sql语句的时候 select后面先用*占位 之后写完再改
    # 在写较为复杂的sql语句的时候 不要想着一口气写完 写一点查一点看一点再写!!!(只要是涉及到数据查询相关的语法都不应该一次性写完 不太现实)
    # 在做多表查询的时候 联表操作和子查询可能会结合使用
    

知识点补充

# 查询平均年龄在25岁以上的部门名称
"""只要是多表查询 就有两种思路    联表    子查询"""
# 联表操作1 先拿到部门和员工表 拼接之后的结果2 分析语义 得出需要进行分组select dep.name from emp inner join depon emp.dep_id = dep.idgroup by dep.namehaving avg(age) > 25;"""涉及到多表操作的时候 一定要加上表的前缀"""
# 子查询select name from dep where id in(select dep_id from emp group by dep_id having avg(age) > 25);# 关键字exists(了解)只返回布尔值 True False返回True的时候外层查询语句执行返回False的时候外层查询语句不再执行select * from emp where exists (select id from dep where id>3);select * from emp where exists (select id from dep where id>300);

今日内容概要

  • navicat可视化界面操作数据库
  • 数据库查询题目讲解(多表操作)
  • python如何操作MySQL(pymysql模块)
  • sql注入问题
  • pymysql模块增删改查数据操作

今日内容详细

Navicat软件

"""
一开始学习python的时候 下载python解释器然后直接在终端书写
pycharm能够更加方便快捷的帮助你书写python代码
excel word pdf我们在终端操作MySQL 也没有自动提示也无法保存等等 不方便开发
Navicat内部封装了所有的操作数据库的命令
用户在使用它的时候只需要鼠标点点即可完成操作 无需书写sql语句
"""

安装

直接百度搜索 有破解版的也有非破解
非破解的有试用期 你如果不嫌麻烦 你就用使用
到期之后重新装再使用 或者破解一下也很简单
https://www.cr173.com/soft/126934.html下载完成后是一个压缩包 直接解压 然后点击安装 有提醒直接点击next即可navicat能够充当多个数据库的客户端navicat图形化界面有时候反应速度较慢 你可以选择刷新或者关闭当前窗口再次打开即可当你有一些需求该软件无法满足的时候 你就自己动手写sql

提示

"""
1 MySQL是不区分大小写的验证码忽略大小写内部统一转大写或者小写比较即可upperlower2 MySQL建议所有的关键字写大写3 MySQL中的注释 有两种--#4 在navicat中如何快速的注释和解注释ctrl + ?  加注释ctrl + ?  基于上述操作再来一次就是解开注释如果你的navicat版本不一致还有可能是ctrl + shift + ?解开注释
"""

练习题

"""
课下一定要把握上课将的这几道题全部自己独立的理解并写出来在解决sql查询问题的时候 不要慌
一步一步慢慢来  最终能够东拼西凑出来就过关了!!!"""
-- 1、查询所有的课程的名称以及对应的任课老师姓名
-- SELECT
--  course.cname,
--  teacher.tname
-- FROM
--  course
--  INNER JOIN teacher ON course.teacher_id = teacher.tid;-- 4、查询平均成绩大于八十分的同学的姓名和平均成绩
-- SELECT
--  student.sname,
--  t1.avg_num
-- FROM
--  student
--  INNER JOIN (
--  SELECT
--      score.student_id,
--      avg( num ) AS avg_num
--  FROM
--      score
--      INNER JOIN student ON score.student_id = student.sid
--  GROUP BY
--      score.student_id
--  HAVING
--      AVG( num ) > 80
--  ) AS t1 ON student.sid = t1.student_id;-- 7、 查询没有报李平老师课的学生姓名
# 分步操作
# 1 先找到李平老师教授的课程id
# 2 再找所有报了李平老师课程的学生id
# 3 之后去学生表里面取反 就可以获取到没有报李平老师课程的学生姓名
-- SELECT
--  student.sname
-- FROM
--  student
-- WHERE
--  sid NOT IN (
--  SELECT DISTINCT
--      score.student_id
--  FROM
--      score
--  WHERE
--      score.course_id IN ( SELECT course.cid FROM teacher INNER JOIN course ON teacher.tid = course.teacher_id WHERE teacher.tname = '李平老师' )
--  );-- 8、 查询没有同时选修物理课程和体育课程的学生姓名
--     (只要选了一门的 选了两门和没有选的都不要)
# 1 先查物理和体育课程的id
# 2 再去获取所有选了物理和体育的学生数据
# 3 按照学生分组 利用聚合函数count筛选出只选了一门的学生id
# 4 依旧id获取学生姓名
-- SELECT
--  student.sname
-- FROM
--  student
-- WHERE
--  student.sid IN (
--  SELECT
--      score.student_id
--  FROM
--      score
--  WHERE
--      score.course_id IN ( SELECT course.cid FROM course WHERE course.cname IN ( '物理', '体育' ) )
--  GROUP BY
--      score.student_id
--  HAVING
--      COUNT( score.course_id ) = 1
--  );-- 9、 查询挂科超过两门(包括两门)的学生姓名和班级
# 1 先筛选出所有分数小于60的数据
# 2 按照学生分组 对数据进行计数获取大于等于2的数据
SELECTclass.caption,student.sname
FROMclassINNER JOIN student ON class.cid = student.class_id
WHEREstudent.sid IN (SELECTscore.student_id FROMscore WHEREscore.num < 60 GROUP BY score.student_id HAVING COUNT( score.course_id ) >= 2 );

pymysql模块

"""
支持python代码操作数据库MySQL
"""
pip3 install pymysql

sql注入

"""
利用一些语法的特性 书写一些特点的语句实现固定的语法
MySQL利用的是MySQL的注释语法
select * from user where name='jason' -- jhsadklsajdkla' and password=''select * from user where name='xxx' or 1=1 -- sakjdkljakldjasl' and password=''
"""
日常生活中很多软件在注册的时候都不能含有特殊符号
因为怕你构造出特定的语句入侵数据库 不安全# 敏感的数据不要自己做拼接 交给execute帮你拼接即可
# 结合数据库完成一个用户的登录功能?
import pymysqlconn = pymysql.connect(host = '127.0.0.1',port = 3306,user = 'root',password = '123456',database = 'day48',charset = 'utf8'  # 编码千万不要加-
)  # 链接数据库
cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)username = input('>>>:')
password = input('>>>:')
sql = "select * from user where name=%s and password=%s"
# 不要手动拼接数据 先用%s占位 之后将需要拼接的数据直接交给execute方法即可
print(sql)
rows = cursor.execute(sql,(username,password))  # 自动识别sql里面的%s用后面元组里面的数据替换
if rows:print('登录成功')print(cursor.fetchall())
else:print('用户名密码错误')

作业布置

"""
1 navicat自己玩一玩
2 练习题一定要搞懂 照着我的思路一遍遍的看敲
3 熟悉pymysql的使用
4 sql注入产生的原因和解决方法 了解
5 思考:如何结合mysql实现用户的注册和登录功能?
"""
1、pymysql模块.pyimport pymysqlconn = pymysql.connect(host = '127.0.0.1',port = 3306,user = 'root',password = '123456',database = 'day48',charset = 'utf8'  # 编码千万不要加-
)  # 链接数据库
cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)  # 产生一个游标对象(就是用来帮你执行命令的)
"""
cursor=pymysql.cursors.DictCursor将查询结果以字典的形式返回
"""
sql = 'select * from teacher;'
res = cursor.execute(sql)
# print(res)  # execute返回的是你当前sql语句所影响的行数  改返回值一般不用
# 获取命令执行的查询结果
# print(cursor.fetchone())  # 只拿一条
# print(cursor.fetchall())  # 拿所有
# print(cursor.fetchmany(2))  # 可以指定拿几条
print(cursor.fetchone())
print(cursor.fetchone())  # 读取数据类似于文件光标的移动
# cursor.scroll(1,'relative')  # 相对于光标所在的位置继续往后移动1位
cursor.scroll(1,'absolute')  # 相对于数据的开头往后继续移动1位
print(cursor.fetchall())
2、sql注入问题.py
# 结合数据库完成一个用户的登录功能?
import pymysqlconn = pymysql.connect(host = '127.0.0.1',port = 3306,user = 'root',password = '123456',database = 'day48',charset = 'utf8'  # 编码千万不要加-
)  # 链接数据库
cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)username = input('>>>:')
password = input('>>>:')
sql = "select * from user where name=%s and password=%s"
# 不要手动拼接数据 先用%s占位 之后将需要拼接的数据直接交给execute方法即可
print(sql)
rows = cursor.execute(sql,(username,password))  # 自动识别sql里面的%s用后面元组里面的数据替换
if rows:print('登录成功')print(cursor.fetchall())
else:print('用户名密码错误')

每日测验(day49)

  • 默写pymysql模块操作MySQL的代码及主要方法

  • 什么是sql注入,如何避免

    (ps:sql注入有很多种类型,我们只是介绍了其中最具代表性的一种来诠释,感兴趣的可以自己再去百度查看完整的sql注入种类及解决方式)

昨日内容回顾

  • Navicat软件的使用

    """
    作为开发 我们使用软件的频率较高 一般不用直接书写sql语句
    快速完成库 表的创建 等等...
    """
    
  • 数据库练习题

    """
    1 面对复杂的查询题目的时候 不要捉急 sql语句不要想着一口气写完 分步书写
    2 只要是涉及到多表查询的时候 肯定用到联表操作和子查询联表操作 你可以无限制的联N多张表将两张表的结果起别名 变成了一张表之后再去另外一张表拼接再起别名再去拼接...
    3 一定要把昨天上课将的练习题自己能够理解并敲出来
    """
    
  • pymysql模块

    # 直接安装 无需考虑版本
    pip3 install pymysqlimport pymysqlconn = pymysql.connect(host = '127.0.0.1',port = 3306user = 'root',password = '123456',  # 还可以简写passwd = '123456'database = 'db666',  # 还可以简写db = 'db666'charset = 'utf8'  # 千万不要加横杆
    )
    # cursor = conn.cursor()  # 括号内不加参数的话 那么查询出来的数据是元组的形式 数据不够明确 容易混乱
    cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)  # 字典形式返回数据 数据有具体的描述信息 更加的合理方便sql = 'select * from user'
    affect_rows = cursor.execute(sql)  # 返回值是当前sql语句执行的受影响的行数
    cursor.fetchone()  # 只能结果的一条  数据本身
    cursor.fetchall()  # 拿所有        列表套多个数据
    cursor.fetchmany(n)  # 指定获取几条
    """
    上述三个方法在读取数据的时候有一个类似于文件指针的特点
    """
    cursor.scroll(1,'relative')  # 相对于光标所在的当前位置往后移动
    cursor.scroll(1,'absolute')  # 相对于数据开头往后移动
    
  • sql注入

    """
    就是利用一些特殊字符 结合软件固定的一些语句句式
    非法侵入并违规操作利用MySQL注释的语法 造成了sql注入的问题用户不需要属于用户名和密码也能够登录并且获取到整个用户表的数据日常应用软件在获取用户输入的内容时 都会限制一些特殊符号的输入如何解决上述问题?所有敏感的信息不要自己去做拼接操作 交互固定的模块帮你去过滤数据防止sql注入在pymysql中 execute就能够帮你过滤
    """
    # sql注入
    sql = "select * from user where username='%s' and password='%s'"%(username,password)
    # 不要自己拼接
    sql = "select * from user where username=%s and password=%s"
    execute(sql,(username,password))  # 只能识别%s
    

pymysql补充

# 1.针对增删改 pymysql需要二次确认才能真正的操作数据
import pymysqlconn = 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)# 增
sql = 'insert into user(name,password) values(%s,%s)'
# rows = cursor.execute(sql,('jackson',123))
rows = cursor.executemany(sql,[('xxx',123),('ooo',123),('yyy',123)])
print(rows)
# conn.commit()  # 确认
# 修改
# sql = 'update user set name="jasonNB" where id=1'
# rows = cursor.execute(sql)
# print(rows)
# conn.commit()  # 确认
# 删除
sql = 'delete from user where id=7'
rows = cursor.execute(sql)
print(rows)
conn.commit()  # 确认
# 查
# sql = 'select * from user'
# cursor.execute(sql)
# print(cursor.fetchall())"""
增删改查中删改增它们的操作设计到数据的修改 需要二次确认
"""# 还可以一次性插入N多条数据
rows = cursor.executemany(sql,[('xxx',123),('ooo',123)])

今日内容概要

今日内容基本都是了解知识点,作为一名开发人员你在工作中基本用不到

  • 视图(了解)
  • 触发器(了解)
  • 事务(需要掌握)
  • 存储过程(了解)
  • 内置函数(了解)
  • 流程控制(了解)
  • 索引理论(了解 日后再去扩展)

今日内容详细

视图(了解)

  • 什么是视图

    """
    视图就是通过查询得到一张虚拟表,然后保存下来,下次可以直接使用
    其实视图也是表
    """
    
  • 为什么要用视图

    """
    如果要频繁的操作一张虚拟表(拼表组成的),你就可以制作成视图 后续直接操作
    """
    
  • 如何操作

    # 固定语法
    create view 表名 as 虚拟表的查询sql语句# 具体操作
    create view teacher2course as
    select * from teacher INNER JOIN course
    on teacher.tid = course.teacher_id
    ;
    
  • 注意

    """
    1 创建视图在硬盘上只会有表结构 没有表数据(数据还是来自于之前的表)
    2 视图一般只用来查询 里面的数据不要继续修改 可能会影响真正的表
    """
    
  • 视图到底使用频率高不高呢?

    """
    不高
    当你创建了很多视图之后 会造成表的不好维护
    """
    # 总结视图了解即可 基本不用!!!
    

触发器(了解)

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

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

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

基本语法结构

create trigger 触发器的名字  before/after insert/update/delete on 表名
for each row
beginsql语句
end# 具体使用 针对触发器的名字 我们通常需要做到见名知意
# 针对增
create trigger tri_before_insert_t1  before insert on t1
for each row
beginsql语句
end
create trigger tri_after_insert_t1  after insert on t1
for each row
beginsql语句
end
"""针对删除和修改 书写格式一致"""ps:修改MySQL默认的语句结束符  只作用于当前窗口delimiter $$  将默认的结束符号由;改为$$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
);
"""
当cmd表中的记录succes字段是no那么就触发触发器的执行去errlog表中插入数据
NEW指代的就是一条条数据对象
"""
delimiter $$
create trigger tri_after_insert_cmd after insert on cmd
for each row
beginif NEW.success = 'no' theninsert 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;

事务

  • 什么是事务

    """
    开启一个事务可以包含多条sql语句 这些sql语句要么同时成功
    要么一个都别想成功 称之为事务的原子性
    """
    
  • 事务的作用

    """
    保证了对数据操作的安全性
    """
    eg:还钱的例子egon用银行卡给我的支付宝转账10001 将egon银行卡账户的数据减1000块2 将jason支付宝账户的数据加1000块你在操作多条数据的时候可能会出现某几条操作不成功的情况
    
  • 事务的四大特性

    """
    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';"""
    总结当你想让多条sql语句保持一致性 要么同时成功要么同时失败 你就应该考虑使用事务
    """
    

    存储过程(了解)

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

    它的内部包含了一系列可以执行的sql语句,存储过程存放于MySQL服务端中,你可以直接通过调用存储过程触发内部sql语句的执行

    基本使用

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

    三种开发模型

    第一种

    """
    应用程序:程序员写代码开发
    MySQL:提前编写好存储过程,供应用程序调用好处:开发效率提升了 执行效率也上去了
    缺点:考虑到认为元素、跨部门沟通的问题  后续的存储过程的扩展性差
    """
    

    第二种

    """
    应用程序:程序员写代码开发之外 设计到数据库操作也自己动手写
    优点:扩展性很高
    缺点:开发效率降低编写sql语句太过繁琐 而且后续还需要考虑sql优化的问题
    """
    

    第三种

    """
    应用程序:只写程序代码 不写sql语句 基于别人写好的操作MySQL的python框架直接调用操作即可         ORM框架
    优点:开发效率比上面两种情况都要高
    缺点:语句的扩展性差 可能会出现效率低下的问题
    """
    

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

  • 存储过程具体演示

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

    在pymysql模块中如何调用存储过程呢?

    import pymysqlconn = 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判断
    delimiter //
    CREATE PROCEDURE proc_if ()
    BEGINdeclare i int default 0;if i = 1 THENSELECT 1;ELSEIF i = 2 THENSELECT 2;ELSESELECT 7;END IF;
    END //
    delimiter ;
    # while循环
    delimiter //
    CREATE PROCEDURE proc_while ()
    BEGINDECLARE num INT ;SET num = 0 ;WHILE num < 10 DOSELECTnum ;SET num = num + 1 ;END WHILE ;
    

    索引

    ps:数据都是存在与硬盘上的,查询数据不可避免的需要进行IO操作

    索引:就是一种数据结构,类似于书的目录。意味着以后在查询数据的应该先找目录再找数据,而不是一页一页的翻书,从而提升查询速度降低IO操作

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

    • primary key
    • unique key
    • index key

    注意foreign key不是用来加速查询用的,不在我们的而研究范围之内

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

    本质

    通过不断的缩小想要的数据范围筛选出最终的结果,同时将随机事件(一页一页的翻)

    变成顺序事件(先找目录、找数据)

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

    一张表中可以有多个索引(多个目录)

    索引虽然能够帮助你加快查询速度但是也有缺点

    """
    1 当表中有大量数据存在的前提下 创建索引速度会很慢
    2 在索引创建完毕之后 对表的查询性能会大幅度的提升 但是写的性能也会大幅度的降低
    """
    索引不要随意的创建!!!
    

    b+树

    """
    只有叶子节点存放的是真实的数据 其他节点存放的是虚拟数据 仅仅是用来指路的
    树的层级越高查询数据所需要经历的步骤就越多(树有几层查询数据就需要几步)一个磁盘块存储是有限制的
    为什么建议你将id字段作为索引占得空间少 一个磁盘块能够存储的数据多那么久降低了树的高度 从而减少查询次数
    """
    

    聚集索引(primary key)

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

    辅助索引(unique,index)

    查询数据的时候不可能一直使用到主键,也有可能会用到name,password等其他字段

    那么这个时候你是没有办法利用聚集索引。这个时候你就可以根据情况给其他字段设置辅助索引(也是一个b+树)

    """
    叶子节点存放的是数据对应的主键值先按照辅助索引拿到数据的主键值之后还是需要去主键的聚集索引里面查询数据
    """
    

    覆盖索引

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

    # 给name设置辅助索引
    select name from user where name='jason';
    # 非覆盖索引
    select age from user where name='jason';
    

    测试索引是否有效的代码

    感兴趣就自己试一试 不感兴趣直接忽略

    **准备**​```mysql
    #1. 准备表
    create table s1(
    id int,
    name varchar(20),
    gender char(6),
    email varchar(50)
    );#2. 创建存储过程,实现批量插入记录
    delimiter $$ #声明存储过程的结束符号为$$
    create procedure auto_insert1()
    BEGINdeclare i int default 1;while(i<3000000)doinsert into s1 values(i,'jason','male',concat('jason',i,'@oldboy'));set i=i+1;end while;
    END$$ #$$结束
    delimiter ; #重新声明分号为结束符号#3. 查看存储过程
    show create procedure auto_insert1\G #4. 调用存储过程
    call auto_insert1();
    ​```​```mysql
    # 表没有任何索引的情况下
    select * from s1 where id=30000;
    # 避免打印带来的时间损耗
    select count(id) from s1 where id = 30000;
    select count(id) from s1 where id = 1;# 给id做一个主键
    alter table s1 add primary key(id);  # 速度很慢select count(id) from s1 where id = 1;  # 速度相较于未建索引之前两者差着数量级
    select count(id) from s1 where name = 'jason'  # 速度仍然很慢"""
    范围问题
    """
    # 并不是加了索引,以后查询的时候按照这个字段速度就一定快
    select count(id) from s1 where id > 1;  # 速度相较于id = 1慢了很多
    select count(id) from s1 where id >1 and id < 3;
    select count(id) from s1 where id > 1 and id < 10000;
    select count(id) from s1 where id != 3;alter table s1 drop primary key;  # 删除主键 单独再来研究name字段
    select count(id) from s1 where name = 'jason';  # 又慢了create index idx_name on s1(name);  # 给s1表的name字段创建索引
    select count(id) from s1 where name = 'jason'  # 仍然很慢!!!
    """
    再来看b+树的原理,数据需要区分度比较高,而我们这张表全是jason,根本无法区分
    那这个树其实就建成了“一根棍子”
    """
    select count(id) from s1 where name = 'xxx';
    # 这个会很快,我就是一根棍,第一个不匹配直接不需要再往下走了
    select count(id) from s1 where name like 'xxx';
    select count(id) from s1 where name like 'xxx%';
    select count(id) from s1 where name like '%xxx';  # 慢 最左匹配特性# 区分度低的字段不能建索引
    drop index idx_name on s1;# 给id字段建普通的索引
    create index idx_id on s1(id);
    select count(id) from s1 where id = 3;  # 快了
    select count(id) from s1 where id*12 = 3;  # 慢了  索引的字段一定不要参与计算drop index idx_id on s1;
    select count(id) from s1 where name='jason' and gender = 'male' and id = 3 and email = 'xxx';
    # 针对上面这种连续多个and的操作,mysql会从左到右先找区分度比较高的索引字段,先将整体范围降下来再去比较其他条件
    create index idx_name on s1(name);
    select count(id) from s1 where name='jason' and gender = 'male' and id = 3 and email = 'xxx';  # 并没有加速drop index idx_name on s1;
    # 给name,gender这种区分度不高的字段加上索引并不难加快查询速度create index idx_id on s1(id);
    select count(id) from s1 where name='jason' and gender = 'male' and id = 3 and email = 'xxx';  # 快了  先通过id已经讲数据快速锁定成了一条了
    select count(id) from s1 where name='jason' and gender = 'male' and id > 3 and email = 'xxx';  # 慢了  基于id查出来的数据仍然很多,然后还要去比较其他字段drop index idx_id on s1create index idx_email on s1(email);
    select count(id) from s1 where name='jason' and gender = 'male' and id > 3 and email = 'xxx';  # 快 通过email字段一剑封喉
    ​```#### 联合索引​```mysql
    select count(id) from s1 where name='jason' and gender = 'male' and id > 3 and email = 'xxx';
    # 如果上述四个字段区分度都很高,那给谁建都能加速查询
    # 给email加然而不用email字段
    select count(id) from s1 where name='jason' and gender = 'male' and id > 3;
    # 给name加然而不用name字段
    select count(id) from s1 where gender = 'male' and id > 3;
    # 给gender加然而不用gender字段
    select count(id) from s1 where id > 3; # 带来的问题是所有的字段都建了索引然而都没有用到,还需要花费四次建立的时间
    create index idx_all on s1(email,name,gender,id);  # 最左匹配原则,区分度高的往左放
    select count(id) from s1 where name='jason' and gender = 'male' and id > 3 and email = 'xxx';  # 速度变快
    ​```总结:上面这些操作,你感兴趣可以敲一敲,不感兴趣你就可以不用敲了,权当看个乐呵。理论掌握了就行了慢查询日志设定一个时间检测所有超出该时间的sql语句,然后针对性的进行优化!

作业

  • 复习整理数据相关所有知识点

  • 整理今日内容相关博客

  • 练习数据库查询题目:https://www.cnblogs.com/Dominic-Ji/p/10875493.html

    能做几道做几道,不强制要求。掌握课上讲的题目解决思路即可

1、pymysql补充.py
import pymysqlconn = 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)# 增
sql = 'insert into user(name,password) values(%s,%s)'
# rows = cursor.execute(sql,('jackson',123))
rows = cursor.executemany(sql,[('xxx',123),('ooo',123),('yyy',123)])
print(rows)
# conn.commit()  # 确认
# 修改
# sql = 'update user set name="jasonNB" where id=1'
# rows = cursor.execute(sql)
# print(rows)
# conn.commit()  # 确认
# 删除
sql = 'delete from user where id=7'
rows = cursor.execute(sql)
print(rows)
conn.commit()  # 确认
# 查
# sql = 'select * from user'
# cursor.execute(sql)
# print(cursor.fetchall())"""
增删改查中删改增它们的操作设计到数据的修改 需要二次确认
"""
2、存储过程.py
import pymysqlconn = 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())

老男孩数据库学习记录相关推荐

  1. 达梦数据库学习记录-包含安装、创建、体系结构、表空间用户模式对象管理备份与还原等

    达梦数据库DCA学习记录 目录 达梦数据库以及认证体系简单介绍 安装DM8数据库及常见问题解决办法 创建数据库.数据库实例及相关知识点介绍 数据库连接 数据库启动与关闭 DM8线程 DM8逻辑存储结构 ...

  2. 数据库学习记录806

    1. (1)基本概念 ① 属性和域: 每个事物有很多属性,每个属性对应的取值范围叫做域,所有对域都是原子数据(第一范式) ② 相关名词 n元关系:R(D1,D2,D3...Dn)是n元关系,其中关系属 ...

  3. Room数据库学习记录

    Room数据库使用 Room数据库 简介: 优点 Room的三个主要组件 Room的相关依赖 使用Room数据库 使用@Entity创建表 使用@Dao,创建操作数据库的接口 使用@Database, ...

  4. 【MySQL】黑马教程MySQL数据库 | 学习记录笔记

    MySQL概述 MySQL介绍 MySQL是一种关系型数据库(RDBMS),就是建立在关系模型基础上,由多张相互连接的二维表组成的数据库.像Excel表.特点:使用表存储数据,格式统一,便于维护:使用 ...

  5. 数据库学习记录9一文详解多表查询

    目录 多表关系 一对多 多对多 一对一 多表查询概述 数据准备 概述 分类 内连接 外连接 自连接 联合查询 子查询 列子查询 行子查询 表子查询 多表查询 多表关系 一对一 一对多(多对一) 多对多 ...

  6. Mysql 数据库学习记录之空值查询

    关键字:NULL 本文是关于mysql的空值查询,即某一列为空值,即值为NULL. 语法: SELECT        *        FROM        数据库表名      WHERE   ...

  7. 数据库学习记录(上)

    创建一个表 create table student(sno char(10),sname varchar(20),ssex char(2),sage smallint,sdept varchar(2 ...

  8. 数据库学习记录,(数据准备)

    工具:notepad++ 数据表示例 学生表 student{学号,姓名,性别,出生年月日,所在班级} 课程表course{客场号,课程名称,教师编号} 成绩表score{学号,课程号,成绩} 教师表 ...

  9. MySQL学习记录 (一) ----- 有关数据库的基本概念和MySQL常用命令

    相关文章: <MySQL学习记录 (一) ----- 有关数据库的基本概念和MySQL常用命令> <MySQL学习记录 (二) ----- SQL数据查询语句(DQL)> &l ...

最新文章

  1. python教学在线观看-python在线学习
  2. 你手上的PCB怎么制作的?几张动图揭晓工厂生产流程
  3. MFC中访问界面控件的两种方法
  4. mysql 定义年龄属性_sql中定义年龄用什么数据类型,长度为多少?
  5. FU-A分包方式,以及从RTP包里面得到H.264数据和AAC数据的方法
  6. [react] 使用react写一个todo应用,说说你的思路
  7. [vue] 怎么解决vue打包后静态资源图片失效的问题?
  8. 除夕快乐 | 2月11日 星期四 | B站发文回应热搜风波;美团上线“团好货”独立App;国内首家自动驾驶企业获网约车运营许可...
  9. dtoj#4263. duliu
  10. jQuery选择器遇上一些特殊字符
  11. win10想说爱你不容易——安装.net3.5也是一个坑(已有完美解决方法)
  12. 单片机矩阵键盘扫描程序c语言,51单片机矩阵键盘扫描程序(源代码)
  13. 【数学】扩展欧几里得算法
  14. 电力拖动计算机系统考试,电力拖动自动控制系统__考试复习题.docx
  15. WordPress网站配置腾讯云cdn缓存
  16. 戴尔服务器显示器接口类型,戴尔推出UltraSharp U4021QW显示器 采用雷电3接口和5K×2K曲面屏...
  17. 字节架构师发布“绝版”Java并发实现原理剖析JDK源码
  18. 1、CSS中iconfont 彩色图标使用详解
  19. 高级安全Windows防火墙管理单元无法加载。请重新启动正在管理的计算机上的Windows防火墙服务,报错代码:0x6D9
  20. Dev C++可以编译但运行时提示Failed to execute且Error 0:操作成功完成。

热门文章

  1. 人事管理系统是什么?HR系统有什么用?
  2. 索引的数据结构与优缺点
  3. 狗年最后一文[2007-02-16]
  4. CSS filter 有哪些神奇用途
  5. 咸鱼的 GitHub 情报 | 20200111 期
  6. director(director)
  7. Permission denied: user=dr.who, access=WRITE, inode=“/“:root:supergroup:drwxr-xr-x
  8. 三维建模之太空战舰——我们的征途是星辰大海!
  9. office最完整的CAB文件下载
  10. 如何将你的网站提交到Google