zoukankan      html  css  js  c++  java
  • mysql 复习

    关系型数据库核心元素

    • 数据行(一条记录)
    • 数据列(字段)
    • 数据表(数据行的集合)
    • 数据库(数据表的集合,一个数据库中能够有n多个数据表)

    为什么学习数据库

    测试工程师的目的是找出软件的不足,并告诉开发工程师,出现问题的环境,操作步骤和输入输出的数据.而优秀的测试工程师,当测出问题后,还可以告诉开发团队,问题的原因和解决方案.

    常用数据类型

    • 整数,有符号范围(-2147483648 ~ 2147483647) ,无符号范围(0 ~ 4294967295)
    • 小数: decimal, 如 decimal(5,2)表示共存 5位数,小数占2位,整数占3位.
    • 字符串:varchar,范围(0~65533),如 varchar(3) 表示最多存3个字符,一个中文或一个字母都占一个字符
    • 日期时间:datetime,范围(1000-01-01 00:00:00~ 9999-12-31 23:59:59), 如'202-01-01 12:29:59'

    约束

    • 主键(primary key):物理上存储的顺序,int类型,无符号,自动递增的,唯一的标识,其中数据不可重复
    • 非空(not null): 此字段不允许填写空值
    • 唯一(unique):此字段的值不允许重复
    • 默认值(default):当不填写此值时会使用默认值,如果填写时以填写为准
    • 外键(foreign key):维护两个表之间的关联关系

    基础知识

    • 一个 byte 等于 1个字节 等于 8位 ,8bit

    • short,char 2个字节 16位;

    • int, float 4 个字节 32位;

    • double, long 8个字节 64位;

    • 一个 int 4个字节 等于 32位 ,32bit. 代表多大的范围: 2^32-1

    数据库管理员 DBA 或者运维来维护

    1563506302583

    • localhost是连接
    • 框内是仓库.
    • 一般一个仓库就是一个网站
    • 每个仓库中可以创建非常多的表
    • 只要硬盘够大可以创建非常多的仓库,表.
    • 一个表中可以有很多字段,一个表中可以有很多记录.

    SQL 语言

    • 数据库表操作: 创建,删除
    • 数据操作: 增加,删除,修改,简单查询
    • 数据操作: 查询

    此部分中查询为重点,需要熟练掌握

    SQL 语言编写和运行

    在查询中直接使用 SQL 语句

    ctrl+/ 注释

    ctrl+shift+/ 取消注释

    创建表

    create table 表明(
    	字段名 类型 约束,
    	字段名 类型 约束,
    	...
    )
    例子:创建学生表
    

    删除表

    drop table 表名
    或
    drop table if exists 表名  -- 如果存在则删除
    

    添加数据

    添加一行数据

    格式一: 所有字段设置值,值的顺序与表中字段的顺序对应

    • 说明:主键列是自动增长,插入时需要占位,通常使用0 或者default 或者 null 来占位,插入成功后以实际数据为准
    insert into 表名 values(...)
    

    格式二:部分字段设置值,值的顺序与给出的字段顺序对应

    insert into 表名(字段1,...) values(值1,...)
    例如:插入一个学生,只设置姓名
    insert into students(name) values('老夫子')
    
    插入多条数据
    insert into 表名(字段1) values(值1),(值2),(值3)...
    或
    insert into students values('值1','值2','值3'...),('值1','值2','值3'...),('值1','值2','值3'...)
    

    执行一条语句会比多条语句的效率高

    修改

    格式:
    update 表名 set 列1=值1,列2=值2... where 条件
    (如果没有条件则改对应目标列的所有)
    例:修改id 为5 的学生数据,姓名改为狄仁杰,年龄改为20
    update student set name='狄仁杰',age=20 where id=5
    

    删除

    
    

    增加表字段

    alert table 表名 add 字段 类型
    

    查询

    select * from students
    (* 代表的是所有"列")
    别名(例子):
    select name as 姓名 from students
    给表起别名的好处:
    select s.name,s.age from student as s,class as c;
    

    去重

    select distinct 字段 from 表名
    select distinct sex from student
    如果是多列,按照多列的标准:
    select distinct 字段1,字段2 from 表名
    

    条件

    • 使用 where 子句 对表中的数据筛选,符号条件的数据会出现在结果集中
    • 语法如下:
    select 字段1,字段2... from 表名 where 条件;
    例子:
    select * from students where id=1;
    
    • where 后面支持多种运算符,进行条件的处理
      • 比较运算
      • 逻辑运算
      • 模糊运算
      • 范围查询
      • 空判断
    查询'1班'以外的学生信息:
    select * from students where class!='班'
    或
    select * from students where class<>'班'
    例子2:查询年龄小于20的女同学
    select * from student where age<20 and sex='女'
    例子3:查询女学生或'1班'的学生
    select * from student where sex='女' or class='1班'
    例子4:查询非天津的学生
    select * from student where not hometown='天津'
    

    比较运算符

    模糊查询

    • like
    • % 标识任意多个任意字符
    • _ 标识一个任意字符
    例子1:查询姓孙的学生
    select * from students where name like '孙%';
    例子2:查询姓孙且名字是一个字的学生
    select * from students where name like '孙_';
    例子3:查询叫乔的学生
    select * from students where name like '%乔';
    例子4:查询姓名包含白的学生
    select * from students where name like '%白%'; 
    例子5:查询名字是两个字的学生
    select * from students where name like '__';
    例子6:查询年龄为18至20的学生
    select * from students where age>18 and age<20;
    或
    select * from students where age between 18 and 20;
    
    空判断
    例子:判断没有填写card的
    select * from students where card='';
    select * from students where card is null;
    

    null 和 '' 不一样

    null 在插入数据后,没有生成后旧为null

    排序

    • 为了方便查看数据,可以对数据进行排序

    • 语法:

    select * from 表名
    order by 列1 asc|desc,列2 asc|desc...
    
    • 将行数据按照列1进行排序,如果某些行列1的值相同时,则按照2排序,以此类推

    • 默认按照列值从小到大排列

    • asc 从小到大排列,即升序

    • desc 从大到小排序,即降序

    • 例1:查询所有学生信息,按年龄从小到大排序

    select * from student order by age;
    
    • 例子2:查询所有学生信息,按年龄从大到小排序,年龄相同时,再按学号从小到大排序
    select * from students order by age desc,studentNo;
    
    • 例子3:查询所有学生信息,按班级从小到大排序,班级相同时,再按学号从小到大排序.
    select * from students order by class ,studentNO;
    
    对中文字符排序
    select * from students order by convert(name using gbk)
    

    聚合函数

    统计,查询总数
    统计行:
    select count(*) from students
    统计列:
    select count(name) from students
    
    • 例子2:查询女生的最大年龄
    select max(age) from students where sex='女';
    
    • 例子3:查询1班的最小年龄
    select min(age) from students where class='1'
    
    • 例子4:查询北京学生的年龄总和
    select sum(age) from students where hometown='北京'
    
    • 例子5:查询女生的平均年龄
    select avg(age) from students where sex='女';
    
    • 例子6:查询所有学生的最大年龄,最小年龄,平均年龄
    select max(age) as 最大年龄,min(age) as 最小年龄,avg(age) as 平均年龄 from students;
    
    • 例子7: 1班共有第多少个学生
    select count(*) from students where  class='1班'
    
    • 例子8: 查询3班年龄小于18岁的同学有几个
    select count(*) from students where class='3班' and age<18; 
    

    分组 group by

    分组的字段(依据.'group by之后的')会在结果集中列出来

    • 按照字段分组,表示此字段相同的数据会被放到一个组中
    • 分组后,分组的依据列会显示在结果集中,其他列不会显示在结果集中
    • 可以对分组后的数据进行统计,做聚合运算

    语法:

    select 列1,列2,聚合... from 表名 group by 列1,列2...
    例1:查询各种性别的人数
    select sex,count(*) from students group by sex
    例1: 查询各种年龄的人数
    select age,count(*) from students group by age
    

    1563527161459

    select name from stu group by name;
    感觉像去重: select distinct name from ....
    
    • 例子:查询各个班级学生的平均年龄最大年龄最小年龄
    select avg(age),max(age),min(age) from students group by class;
    

    select 后面跟着的 参数字段,都会作为列名称

    多字段的分组
    select class,sex,count(*) from student group by class,sex
    

    在分组的时候,每一行数据,班级和性别都相同才会分到一组中.

    • 例子:用分组实现统计班级男生总人数
    原: select count(*) from students where sex='男'
    现: select sex,count(*) from students group by sex having sex="男"
    
    • 例子:查询1班除外其他班级学生的平均年龄,最大年龄,最小年龄
    select class,avg(age),max(age),min(age) from students where class!='1班' group by class having class!='1班';
    

    1563530634190

    分页

    • 当数据量过大时,在一页中查看数据是一件非常麻烦的事情
    • 语法
    select * from 表名 limit start,count;
    从start 开始,获取count 条数据
    start 索引从0开始
    

    例子:查询前3行学生信息

    select * from student limit 0,3;

    select * from student limit 7;
    相当于: select * from student limit 0,7
    简写了起始位.
    

    多表查询(连接查询) 重要

    1563605474785

    select * from students,scroo where students.studentno=scores.studentno;
    

    第一种会产生临时表,会占很大内存,会产生"笛卡儿积"

    等值连接(内连接)

    • 方式二(又称内连接)
    select * from 表1 inner join 表2 on 表1.列 =表2 列
    select * from students inner join scores on students.studentno=scores.studentno
    

    性能高!不会产生笛卡儿积,不会产生临时表

    • 例子:统计每个班级中男女生学生人数,按照班级升序排序
    select class,sex,count(*) from students group by class,sex;
    
    • 例子20:查询年龄最小的学生的全部信息

    • 例5:查询王昭君的成绩,要求显示姓名,课程名,成绩

    select 姓名,课程名,成绩 from 成绩表  inner join 课程表 on 课程号=课程号 inner join 学生表 on 学生表学号=课程表学号
    
    • 例子7:查询男生中最高成绩,要i求显示姓名课程名,成绩
    select 姓名,课程名,成绩 from 成绩表  inner join 课程表 on 课程号=课程号 inner join 学生表 on 学生表学号=课程表学号 where sex='男' order by score desc limit 1
    

    左连接

    1563605439980

    select * from 表1 left join 表2 on 表1.列=表2.列
    
    • 例子1:查询所有学生的成绩,包括没有成绩的学生
    select * from students left join scores on students.studentno=scores.studentmo;
    

    left join 左边前面的表就是主表.join 后面的表是右表

    1563604670258

    • 例子2:查询所有学生的成绩,包括没有成绩的学生,需要显示课程名
    select * from students stu left join scores sc on stu.studentNo=sc.studentNo left join courses cs on cs.courseNo =sc.courseNo;
    

    右连接

    • select * from 表1 right join 表2 on 表1.列=表2.列

    • 例子1:查询所有课程的成绩,包括没有成绩的课程

    select * from scores sc right join coures cs on cs.courseNo =sc.courseNo
    
    • 例子2:查询所有课程的成绩,包括没有成绩的课程,包括学生信息

    1563605413445

    select * from scores  right join students on students.studentNo=scores.studentno left join coures on scores.courseNo=courses.courseno
    

    自关联查询

    例子1:查询河南省的所有城市

    select * from areas,areas_copy where areas.aid=areas_copy.pid and areas.atitle='河南省';
    

    1563690325141

    或 (不拷贝两个表了,一个表查询多次)

    • 数据源,一个表查多次
    select * from areas as sheng,areas as shi where sheng.aid=shi.pid and sheng.atitle='河南省';
    
    自关联 关联3次
    • 例子2:查询郑州市的所有区县
    select * from areas as sheng,areas as shi where sheng.aid=shi.pid and sheng.atitle='郑州市';
    
    • 例子3:查询河南省的所有区县
    select * from areas as sheng,areas as shi ,areas as qu where sheng.aid=shi.pid and sheng.atitile='河南省' and shi.aid=qu.pid;
    

    子查询

    • 在一个 select 语句中,嵌入了另外一个select 语句,那么被嵌入的 select语句称之为子查询语句

    主查询

    • 主要查询的对象,第一条 select 语句

    主查询和 子查询的关系

    • 子查询是嵌入到主查询中
    • 子查询是辅助主查询的,要么充当条件,要么充当数据源
    • 子查询是可以独立存在的语句,是一条完整的select 语句

    子查询分类

    • 标量子查询:子查询返回的结果是一个数据(一行一列)
    • 列子查询:返回的结果是一列(一列多行)
    • 行子查询:返回的结果是一行(一行多列)
    • 表级子查询:返回的结果是多行多列

    标量子查询

    • 例子1: 查询班级学生的平均年龄
    查询大于平均年龄的学生;(需要先查出平均值,要操作两次,且结果有时间错误)
    select * from students  where age > 21.4167;
    一条语句查询出,**被括号括起来的是的子查询**
    select * from students where age > (select avg(age) from students).
    
    • 例子2: 查询王昭君的语文成绩,要求只显示成绩
    select scores from scores where studentNo=(select studentNo from students where name='王昭君')
    and courseNo=(select courseNo from courses where name='语文')
    

    列级子查询

    列级子查询返回一列多行

    成绩表中根据学号查成绩

    select * from scores where studentNo in ('002','006')

    1563715255420

    select * from scores where studentNo in (select studentNo from students where age=18)

    1563715753344

    行级子查询

    例子4:查询男生中年龄最大的学生信息

    多个条件是且的关系可以这么写:

    select * from students where sex='男' and age=26

    select * from students where (sex,age)=('男',26);

    select sex,age from students where sex='男' order by age desc limit 1;

    1563716776394

    select * from students where (sex,age)=(select sex,age from students where sex='男' order by age desc limit 1)

    1563716862416

    表级子查询

    例子5:查询数据库和系统测试的课程成绩

    select * from scores inner join courses on scores.courseNo=courses.courseNo where courses.name in ('数据库','系统测试')

    这种方式有一种不好的地方:在过滤之前数据量较多.

    select * from courses where name in ('数据库','系统测试')

    1563716433337

    优化后:

    select * from scores inner join (select * from courses where name in ('数据库','系统测试')) as c on scores.courseNo=c.courseNo;
    

    子查询中特定关键字使用

    • in 范围
      • 格式: 主查询 where 条件 in (列子查询)
    • any|some 任意一个
      • 格式:主查询 where 列 = any (列子查询)
      • 在条件查询的结果中匹配任意一个即可,等价于 in
    • all
      • 格式:主查询 where 列 = all(列子查询):等于里面所有
      • 格式:主查询 where 列 <> all(列子查询):不等于其中所有
    select * from students where age in (select age from students where age between 18 and 20)
    
    any:
    select * from students where age=any(select age from students where age between 18 and 20)
    
    
    

    案例

    函数 round() 保留小数点

    把一个表中查询的结果插入另一个表中

    insert into goods_cates(cate_name) select distinct cate from goods;

    查询演练-数据分表

    select * from goods inner join goods_cates on goods.cate==goods_cates.cate_name

    1563796381051

    现在将id1 列的内容更新至 cate 列中

    update goods inner join goods_cates on goods.cate=goods_cates.cate_name set goods.cate=goods_cates.id;

    高级

    E-R 模型

    E-R模型的基本元素是:实体,联系和属性

    • E 表示entry,实体:一个数据对象,描述具有相同特征的事务
    • R 表示relationship,联系:表示一个或多个实体之间的关联关系,关系的类型包括包括一对一,一对多,多对多.
    • 属性:实体的某一特性为属性

    关系也是一种数据,需要通过一个字段存储在表中

    1. 实体A对实体B为1对1,则在表A或表B中船舰一个字段,存储另一个表的主键值.

    1563797586482

    让不常使用的表来维护共同特征数据(如拆分出了家庭地址,由家庭地址表维护学生学号字段.学生表不维护地址数据)

    1. 实体A对实体B为1对多:在表B中创建一个字段,存储表A的主键值

    1563798130855

    当一对多的关系中,应该让多的那张表来存关系

    1. 实体A 对实体B 为多对多:新建一张表C,这个表只有两个字段,一个用于存储A的主键值,一个用于存储B的主键值.

    1563798513296

    一个课程可以由多个学生来学,一个学生可以学多个课程.(多对多的关系)

    多对多的关系通常会用中间表来记录

    命令行客户端

    常用命令:

    连接
    mysql -uroot -p 回车 输入密码
    查看所有仓库
    show databases;
    使用某个仓库
    use 仓库名称;
    查看所有的表:
    show tables;
    查看表结构:
    desc student;
    show create table students;
    出现中文乱码这么操作消除乱码:
    set charset gbk;
    

    备份:

    mysqldump -uroot -p密码 备份的数据库名称>新名称.sql

    恢复:
    mysql -uroot -p 新数据库名 < 备份的数据库名称.sql

    根据提示输入mysql 密码

    内置函数

    字符串函数
    • 拼接字符串 concat(str1,str2...)

    select concat(12,34,'ab');

    • 包含字符个数length(str)

    select length('abc');

    • 截取字符串
      • left(str,len) 返回字符串str 的左端 len个字符
      • right(str,len)返回字符串str的右端len个字符
      • substring(str,pos,len)返回字符串str的位置pos起len个字符

    select substring('abc123',2,3)

    • 去除空格
      • ltrim(str)返回删除了左空格的字符串str
      • rtrim(str)返回删除了右空格的字符串str
    日期时间函数
    • 当前日期
      • select current_date()
    • 当前时间current_time()
      • select current_time()
    • 当前日期时间now()
      • select now()
    • 日期格式化 date_format(date,format)
      • 参数format可选值如下
        • %Y 获取年,返回完整年份
        • %y 获取年,返回简写年份
        • %m 获取月,返回月份
        • %d 获取日,返回天值
        • %H 获取时,返回24进制的小时数
        • %h 获取时,返回12进制的小时数
        • %i 获取分,返回分钟数
        • %s 获取秒,返回秒数

    流程控制

    • case 语法:等值判断
    • 说明:当值等于某个比较值得时候,对应得结果会被返回;如果所有的比较值都不相等则返回else得结果;如果没有else并且所有比较值都不相等则返回null
    case 值 when 比较值1 then 结果1 when 比较值2 then 结果2 ... else 结果 end
    

    1563859669571

    select 
    case 1 
    when 1 then 'one' 
    when 2 then 'two' 
    else 'zero' 
    end as result;
    

    1563859650761

    自定义函数

    • 创建

    • 语法如下

      delimiter $$
      create function 函数名称(参数列表) returns 返回类型
      begin
      sql语句
      end
      $$
      delimiter ;
      
      
    • 说明:delimiter用于设置分隔符,默认为分号

    • 再"sql 语句"部分编写的语句需要以分号结尾,此时回车会直接执行,所以要创建存储过程前需要指定其它符号作为分隔符,此处使用//,页可以使用其它字符

    • "$$" 用于命令行中

    示例:

    • 要求:创建函数my_trim,用于删除字符串左右两侧的空格
    • step1:设置分隔符

    delimiter $$

    • 创建函数
    create function my_trim(str varchar(100)) returns varchar(100)
    begin
    return ltrim(rtrim(str))
    end
    
    
    • step3: 还原分隔符

    delimiter ;

    使用自定义函数

    select ' abc ',my_trim(' abc ')

    视图

    • 对于复杂的查询,在多个地方被使用,如果需求发生了改变,需要更改sql 语句,则需要在多个地方进行修改,维护起来非常麻烦
    • 解决:定义视图
    • 视图本质就是对查询的封装
    • 定义视图,建议以v_开头

    create view 视图名称 as select 语句;

    例子:创建视图,查询学生对应的成绩信息

    select stu.*,cs.courseNo,cs.name cour
    seName,sc.score
    from
    students stu
    inner join scores sc on stu.studentNo=sc.studentNO
    inner join courses cs on cs.courseNo=sc.courseNo;
    
    

    事务

    • 事务广泛的运用于订单系统,银行系统等多种场景
    • 例如:A用户和B用户时银行的储户,现在A要给B转账500元,那么需要做以下几件事:
      1. 检查A的账户余额>500元;
      2. A账户中扣除500元
      3. B账户中增加了500元
    • 所谓事务,它时一个操作序列,这些操作要么都执行,要么都不执行,它是一个不可分割的工作单位.列如:银行对账工作;从一个账号扣款并使另一个账号增款,这两个操作要么都执行,要么都不执行.所以,应该把他们看成一个事务.事务是数据库维护数据一致性的单位,在每个事务结束时,都能保持数据一致性.

    事务命令

    • 表的引擎必须是innodb类型才可以使用事务,这是mysql表的默认引擎.
    • 查看表的创建语句,可以看到engine=innodb
    show create table students;
    
    

    **开启事务:begin; **

    所有操作都成功:commit;

    任何一步失败: rollback;

    索引

    思考:在图书馆中是如何找到一本书的?

    一般的应用系统对比数据库的读写比例在10:1左右,而且插入操作和更新操作很少出现性能问题;当数据库中数据量很大时,查找数据会变得很慢.

    优化方案:索引

    语法:

    show index from 表名;
    
    • 创建索引
    方式一:建表时创建索引
    create table create_index(
    id int primary key,
    name varchar(10) unique,
    age int,
    key(age)
    );
    
    • 主键会自动创建索引,
    • unique也会自动创建索引,
    • key(字段)也会创建索引
    方式二:
    create index 索引名称 on 表名(字段名称(长度))
    create index i_name on test(name(10))
    对已有表创建索引;
    
    • 开启运行时间监测:
    • set profiling=1;
    • 查看执行的时间:
    • show profiles;

    外键 foreign key

    • 查看外键:show create table 表名
    • 外键的作用:用来约束表. 设置外键约束
    方式一:创建数据表的时候设置外键约束
    create table class(
    	id int unsigned primary key auto_increment,
    	name varchar(10)
    );
    
    create table stu(
    	name varchar(10),
    	class_id int unsigned,
    	foreign key(class_id) references class(id)
    );
    
    foreign key(自己的字段) references 主表(主表字段)
    
    方式二: 对于已经存在的数据表设置外键约束
    alter table 从表名 add foreign key(从表字段) references 主表名(主表字段);
    alter table stu add foreign key (class_id) references class(id)
    
    删除外键
    需要先获取外键约束名称
    show create table stu;
    获取名称之后就可以根据名称来删除外键约束
    alter table 表名 drop foreign key 外键名称;
    alter table stu drop foreign key stu_ibfk_i;
    

    在实际开发中,很少会使用到外键约束,会极大的较低表更新的效率

    1563870434231

    篮圈外键

  • 相关阅读:
    min-max 容斥
    集训作业
    UOJ Test Round 3
    uoj Goodbye Dingyou
    Codeforces Round #516 (Div. 1) 题解
    Codeforces Round #517(Div. 1) 题解
    概率论(Ⅱ)
    Berlekamp-Massey算法学习笔记
    多项式取模优化线性递推总结
    [ZJOI2019]线段树
  • 原文地址:https://www.cnblogs.com/521world/p/11389251.html
Copyright © 2011-2022 走看看