• 数据库mysql详细教学


    1024 byte 构成 1 kb

    1024 KB => 1MB

    1024 MB => 1GB

    1024 GB => 1TB

    1024 TB => 1PB

    内存的数据,断电后会丢失。外存的数据,断电后数据还在~

    “持久化” 这样的次,意思就是把数据写到硬盘上。


    mysql的第一组基本操作:数据库操作

    1、查看当前数据库

    show databases:

    1)show 和 databases 之间有一个或者多个空格

    2)注意是databases,不是database。

    3)使用 英文分号 结尾。(客户端里的任何一个sql都需要使用 分号 来结尾) 

    2、创建数据库

    可以指定字符集。

    补充:

    计算机里,不同的字符集下,表示一个汉字所需要的字节不同。

    平时常用的:

    1、gbk windows 简体中文版,默认字符集。 2个字节表示一个汉字

    2、utf8 更通用的字符集。不仅仅能表示中文 通常是3个字节白哦是一个汉字的

    create database 数据库名 charset utf8(字符集)
    

    3、选中数据库

    use 数据库名;

    选中数据库,选中之后,会有个提示~ 

    4、删除数据库

    drop database 数据库名

    5、表操作

    5.1查看数据库中的表

     

    一定要先选中数据库再操作!

    5.2创建表

    5.2.1数据类型

    • 字符:char      varchar(可变长度字符串)
    • 时间:data     datatime
    • 整数:tinyint(相当于Byte)    smallint(相当于Short)     int(相当于Integer)    bigint(相当于Long)
    • 浮点:float    double
    • BLOB:存储的是2进制串,和bit[]不一样,只能存最多 64 bit。blob可以存更长,比如要存一个小的图片,存一个小的音频文件。
    • datetime / timestamp:都能表示年月日,时分秒。timestamp:4个字节的时间戳,不太够用了。

    double 和 float 有一个很严重的问题!

    表示有些数据的时候,不能精确表示!(存在误差)

    0.1 + 0.2 = 0.3 => false

     主要市和内存存储结构相关。

    这个表示方式带来的好处,存储空间小,计算速度块,但是可能存在误差。

    使用decimal,是使用了类似于字符串的方式来保存的~ 更精确存储

    但是存储空间更大,计算速度更慢了

    上述类型都是有符号(带有正负的)无符号的不建议使用 

    create table 表名(列名 类型, 列名 类型……);

     

    5.3 查看指定表的表结构

    1. desc 表名;
    2. desc -> describe 的缩写。(描述一个表是啥样的)

    5.4删除表

    drop table 表名;

     创建数据库也有一个 IF [NOT] EXISTS


    eg:单价使用什么类型?

    double (3,1)  不精确!!

    decimal 是更好的选择!!(更精确)

    此处更好的选择是使用  


     性别不止 男 和 女~

    有些字段,看起来是数字,实际上是字符串~

    像身份证,虽然是由数字构成的,但是这个数字不能够参与 +-*/ 算数运算

     5.5 MySQL表的增删改查

    CRUD 即增加(create), 查询(Retrieve), 更新(update),删除(Delete)四个单词的首字母缩写。

    5.5.1新增 / 插入数据

    insert into 表名 values(值,值……);

    values 后这里的个数,类型,顺序要和表头结构匹配~~

    SQL没有字符类型,‘ 和 ‘’ 都可以表示字符串。

    此处还有一种错误数据库字符集没有正确配置引起的~~

    数据库不做任何修改,默认情况下创建的数据库字符集是“拉丁文”字符集,不能表示中文。

    在插入的时候,指定某个 / 某些列来插入 此时 values 后面的内容。就是和values前面的 () 的内容匹配的~

    一次插入 N 个记录,比一次插入一个记录,分N次插入,效率要高一些~~ 

    插入时间的时候,是通过特定格式的字符串来表示时间日期的。形如:‘2023-11-14 02:41:00’ 

    如果想把时间设置为当前时刻,sql 提供了一个特殊的函数,now() 

    5.5.2 查找操作

     eg1:全列查找

    查找整个表,所有行的所有列。

    select * from 表名;

    如果数据量几亿,几十亿执行 select *  操作,肯定会非常危险!!

    降低危险程度,一个简单有效的办法——当你需要操作生产环境的数据库的时候,一定要拉上一个人一起操作。

    eg 2:原来基础上+条件

    查询的时候,针对分数进行变换。比如让查询的math成绩都在原来基础上+10‘

    select name, math+10 from 表名;

    上述查询,数据库服务器硬盘的数据没有发生改变,再次查询,还是+10之前。


    eg 3:查询每个同学的总成绩

    表达式查询,是让列和列之间进行运算。


    eg 4:查询的时候指定别名(相当于起了个小名,更方便理解含义)

    使用 as 关键字


    eg 5:去重查询

    distinct 针对指定列进行去重(把重复行去掉)


    eg 6:按照查询结果排序

    order by 子句,指定某些列进行排序~ 

    排序可能是升序,也可能是降序

    对于mysql来说,如果sql没有指定order by,此时查询结果集的数据顺序,是不可预期的。

    order by 可以根据多个列来排序

    desc 降序(descend)

    asc 表示升序,但如果省略不写,默认就是升序。


    eg 6:条件查询

    在查询的时候,指定筛选条件  符号条件的数据留下,不符合的直接 pass

    需要先描述条件。

    通过 where 子句,搭配上条件表达式,就可以完成条件查询~

    可以直接拿两个列比较~

    条件查询使用表达式作为条件

    查询总分在200分以下的同学

    查询语文成绩大于60分,且英语成绩大于50分的同学。 and

    查询语文成绩大于60,或英语成绩大于50的同学。  or

    and 和 or 的优先级

    一个where 中即存在 and 又存在 or,先执行 and 后执行 or。后边写代码,记得多加()。


    eg7:between and 约定一个前闭后闭 区间(包括两侧边界)

    String 这里的有些方法,就是按照区间来指定的 substr……

    List 这里的有些方法也是按照区间 subList……


    eg8:查询数学成绩是 87 或 98 或 56的同学

    in

    以上写法效率比较低。


    eg9:模糊查询 like

    模糊匹配,不要求元素完全相同,只要满足一定的规则,就可以了~

    like支持两个用法:

    1、使用%代表任意 0 个字符或者N个字符~

    2、使用_代表任意1个字符~

    like ’%藏‘  查询藏结尾的

    like ’%孙%‘ 查询包含孙的

    mysql 效率比较低~

    很容易成为性能瓶颈,模糊匹配更是比较低效的写法,如果这里支持的功能更复杂,反而更拖慢数据库的效率。


    eg10:NULL / null 表示表格这一项为空   

    sql不区分大小写的

    null 和其他数值进行运算,结果还是null

    null结果在条件中,相当于false 了

    <=> 使用这个比较相对运算,就可以处理 null 的比较!

    null <=> null  =》 true

    或者


    eg11:分页查询 limit

    比如一共5000页,一共这么多数据,全都显示出来,一方面,用户看不过来;一方面对于系统的压力也比较大~~

    一页显示10个数据~~

    limit 还可以搭配 offset,声明从哪一条开始查询(从0开始计数)

    limit 3 offset 6;      等价于    limit 6,3;(不太推荐这么写)

    查询总分前三名的同学信息~~

    1、计算每个同学的总成绩

    2、按照成绩排序(降序)

    3、取前三条记录~

    order by 这里可以使用别名,where不能使用

    5.5.3修改操作

    update关键字进行

    update 表名 set 列名 = 值,列名 = 值……where条件;

    order by / limit 等也是可以使用的~

    超过范围了,此时修改不会生效

    修改所有人的成绩为0.5倍。 

    update操作非常危险!

     5.5.4 删除操作

    delete 删除记录(行)

    delete from 表名 where 条件;

    delete from exam_result where name like '孙%';

    不写 where 也没有 limit 就是全部了!这个操作基本相当于删表了(drop table)

    delete from 表还在,里面的数据没了。  l.clear();

    drop table 表和数据都没了。        l=null;

    数据库约束

    约束,就是数据库针对里面的数据能写啥,给出的一组“检验规则”。

    • NOT NULL  必填项
    • UNIQUE   让列的值是唯一的(不和别的行重复,eg:学号,手机号,身份号)
    • DEFAULT   默认值
    • PRIMARY KEY  主键
    • FOREIGN KEY  外键
    • CHECK  在mysql 5 版本中,不支持 

    1、not null

     

    此时表中可以随意插入空值!

    给一个现有的表加约束,也可以,比较麻烦,使用 alter table

    2、unique

     插入/修改数据的时候,先会查询,先看看数据是否已经存在,如果不存在,就能够插入/修改成功。如果存在,则插入/修改失败。

    此时再插入同样的数据报错。

    entry:入口,条目

    补充:数据库在插入前先查询了一下~(只不过查询操作,咱们感知不到)

    因此,这里是多了个查找数据的成本。

    本质上,程序运行 vs 程序员开发效率。

    3、default

    默认值是insert指定列插入的时候,其他未被指定到列就是按照默认值来填充~~ 

     create table 表名(id int, name varchar(20) default '无名氏');

    4、primary key

     主键,一条记录 在表中的“身份标识”        手机号码,身份证号码,学号……

    也是要求唯一,并且不能为空~~

    主键 = unique + not null

    mysql 要求一个表里,只能有一个主键!!

    创建主键的时候,可以使用一个列作为主键,也可以使用多个列作为主键(复合主键)

     create table 表名(id int primary key, name varchar(20));

    一个重要的问题:

    如何给这个记录安排一个主键呢?

    mysql自身只是能够检查是否重复,设置的时候还是靠程序员来设置。

    此处,由很多办法,mysql提供了一个简单粗暴的做法,自增主键~~

    auto_increment

    create table student (id int primary key auto_increment, name varchar(20));

    给自增主键插入数据的时候,可以手动指定一个值,也可以让mysql 自己分配。

    如果让他自己分配,就在insert语句的时候,把 id 设为空即可

    此时可以手动分配,也可以让mysql自己指定~

    但是再次插入的时候,就从序号最大值+1开始了~

    5、foreign key 外键

    create table student (studentId int primary key auto_increment, name varchar(20),classId int,foreign key(classId) references class(classId));

    此时就要求 student 表中的每个记录的 classId 得在 class 表的 classId 中存在! 

    student受到class的约束,就把class叫做student的父表(parent),

    student就是class的子表(child) 

    子类对父类也有约束,被孩子依赖的数据不能删除掉 

    eg:电商类网站

    商品表(id, name, price……)

    订单表(orderId, userId, goodsId, time ……)

    订单表中的goodsId得在 商品表中存在外键约束~

    有一种情况,商品要下架,如何实现?

    给商品表加一列,表示是否下架,此时实现下架并非是delete记录,而是update把是否下架字段进行修改~~   逻辑删除

    表的设计

     设计表,分两步走

    1、梳理清楚需求中的“实体”

    2、梳理清楚实体之间的关系

    实体之间的关系,主要由三种(严格的说是四种)

    1、一对一

       一个学生,只能有一个账号。

       一个账号,只能供一个学生所有

    如何设计表

            1)搞一个大表,包含学生信息 + 账号信息

            account-student(accountId, username, password, studentName……)

            2)搞两个表,相互关联

            account(accountId, username, password);

            student(studentId, name……);

            3)搞两个表

            account(accountId, username, password);

            student(studentId, studentName, accountId);

            后续可以搞一些教师表等,也能和account关联

    2、一对多

        一个班级 可以包含多个学生

        一个学生只能处于一个班级

    两种典型表示方式:

            1)student(studnetId, name);              mysql没有数组类型,不能这么搞,但是redis,是由数组类型的,此时就可以考虑这样的设计

                  class(classId, className, studentIdList)

            2)class(classId, className);

                             1             2001

                             2             2002

                  student(studentId, name, classId);

                                 1              张三       1

                                 2              李四       2

    3、多对多

        一个学生可以选择多个课程,

        一个课程也可以提供给多个学生。

    方式:

            1)student(studentId, name)

                                    1           张三

                                    2           李四

                 course(courseId,name)

                                   1         语文

                                   2         数学 

            需要搞一个 关联表

            student_course(studentId, courseId)

                                            1               1

                                            1               2                张三选了 语文 和 数学

                                            2               1                语文这个课程就提供给了张三和李四~


    把查询和新增联合起来

    把查询结果作为新增的数据~ 

    要求:查询结果得到的列数、类型需要和插入的表的列数、类型匹配。列名不一样没事。


    更复杂的查询

    01聚合查询

    把查询过程中,表的行和行之间进行一定的运算~

    select 指定的列,要么是带有聚合函数的,要么就是得指定的group by的列……

    不能指定一个 非聚合 非 group by 的列

    依赖聚合函数。这些是SQL提供的库函数

    • COUNT 计数

    这个操作,可以理解成,先执行select *

    然后去计算select* 查询结果有多少行~

    有一行名字是空

    • SUM 求和

    sum操作会自动跳过结果为null的行。

    • AVG 平均数

    • MAX
    • MIN

    聚合函数还能搭配表达式使用。求总分的平均分。 


    以上聚合函数默认都是针对这个表的所有类进行聚合~

    有时候,还需要分组聚合(按照制定的字段,把记录分成若干组,每一组分别使用聚合函数)

    员工表

    求每个岗位的平均薪资~就需要使用分组查询 group by 指定一个列,就会把列里的值,相同的分到同一个组

    分组的时候,可以指定条件筛选~~

    先搞清楚,筛选条件是分组前,还是分组后~~

    1、分组前,筛选,使用where条件,求每个岗位的平均薪资,但是抛出 wangwu 同学。

    group by

    2、分组后,筛选,使用having条件~求出每个岗位的平均薪资,刨除老板~~

    having

    3、既抛出wangwu,有抛出老板

    02联合查询

    把多个表联合到一起进行查询~

    笛卡尔积(一种运算),联合查询就是基于这个运算。

    笛卡尔积,其实就是一种排列组合,把两张表的记录 尽可能的排列出N种情况~

         班级表(classId,className)

                            1           2001

                            2           2002

         学生表(studentId,name,classId)

                            1          张三       1

                            2          李四       1

                            3          王五       2

                            4          赵六       2


    学生表和班级表的笛卡尔积结果     

     (studentId,name,classId)          (classId,className)

             1        张三       1                    1        2001

               1        张三       1                    2        2002

             2        李四       1                    1        2001

               2        李四       1                    2        2002

               3        王五       2                    1        2001

             3        王五       2                    2        2002

               4        赵六       2                    1        2001

             4        赵六       2                    2        2002

    有效数据:classId 相同,两个class对的上,就可以使用 where 子句的条件来描述。

    去掉无效数据之后,笛卡尔积里剩余的数据,就是每个同学在哪个班级里这样的信息了。

    基于 笛卡尔积 + 条件 进行查询,此时就是 联合查询 / 多表查询

    select * from student,score where student.id = score.student_id;

    03内连接

    语法:

    inner join……on……

    1. select 字段 from1 别名1 [inner] join2 别名2 on 连接条件 and 其他条件;
    2. select 字段 from1 别名1,表2 别名2 where 连接条件 and 其他条件;

    多表查询一般实现步骤

    1、分析清除需求种,涉及到的信息都在哪些表里~

    2、针对这多个表进行笛卡尔积

    3、筛选出其中有效数据(此处使用学生id作为关联条件)

    4、结合需求中的条件,进一步加强条件

    5、针对列进行精简

    四张表 student, classes, course,  score

    三个实体:学生, 班级, 课程

    学生和班级, 一对多关系

    学生和课程, 多对多关系   score表相当于是关联表

    班级和课程,没关系


    1) 查询“许仙”同学的成绩

    学生表和成绩表进行联合查询。

    1. select sco.score from student stu inner join score sco on stu.id=sco.student_id
    2. and stu.name='许仙';
    3. -- 或者
    4. select sco.score from student stu, score sco where stu.id=sco.student_id and
    5. stu.name='许仙';

    2)查询所有同学的总成绩,及同学的个人信息

    1. -- 成绩表对学生表是多对1关系,查询总成绩是根据成绩表的同学id来进行分组的
    2. SELECT
    3. stu.sn,
    4. stu.NAME,
    5. stu.qq_mail,
    6. sum( sco.score )
    7. FROM
    8. student stu
    9. JOIN score sco ON stu.id = sco.student_id
    10. GROUP BY
    11. sco.student_id;

    3)查询所有同学的成绩,及同学的个人信息

    1. -- 查询出来的都是有成绩的同学,“老外学中文”同学 没有显示
    2. select * from student stu join score sco on stu.id=sco.student_id;
    3. -- 学生表、成绩表、课程表3张表关联查询
    4. SELECT
    5. stu.id,
    6. stu.sn,
    7. stu.NAME,
    8. stu.qq_mail,
    9. sco.score,
    10. sco.course_id,
    11. cou.NAME
    12. FROM
    13. student stu
    14. JOIN score sco ON stu.id = sco.student_id
    15. JOIN course cou ON sco.course_id = cou.id
    16. ORDER BY
    17. stu.id;

    04外连接 

    内连接和外连接都是进行笛卡尔积。但是细节上有所差别~

    内连接:

    外连接加 left / right 关键字

    select name,score from student left join score on student.id = score.student_id;

    当前情况下,这两个表的数据是一一对应的~

    第一个表的每个记录,在第二个表里都有体现。第二个表里的每个记录,在第一个表里也都有体现

    此时内连接和外连接,查询结果相同!

    左外连接:就是以左侧的表为准,左侧表中的所有数据都能体现出来

     

    右外链接,就是以右侧表为准。右侧表中的所有数据都体现出来。

    05自连接

    这个操作本质上是把“行”转成“列”

    SQL中进行条件查询,都是指定 某一列 / 多个列 之间进行关系运算~

    无法行和行之间关系运算~

    有点时候为了实现这种行之间的比较,就需要把行关系转成列关系~

    子连接需要指定表的别名。​​​​​​​

  • 相关阅读:
    使用aspnetcore前后端分离开发,你一定要知道这个
    【web开发】3、Bootstrap基础
    精通Nginx(11)-缓存
    关于机器学习的向量机,都讲了什么
    认识Vue扩展插件
    “轻松实现文件夹批量重命名:使用顺序编号批量改名“
    Mac电脑系统怎么样才能干干净净地卸载应用程序?
    Github 仓库代码合并 + 历史记录保留
    MyBatis ---- 搭建MyBatis
    菜鸡的秋招升级打怪之旅
  • 原文地址:https://blog.csdn.net/m0_67247641/article/details/134135046