MYSQL(1)————初阶

1.计算机的基本结构

数据库上面的数据,都是保存在硬盘上面的,是一种持久化存储的方式;通过网络可以进行跨主机之间的通信;

一个电脑:
1)CPU:叫做中央处理器,这是计算机最核心的部件
2)存储器:1)内存:主机自带
         2)外存:C盘+D盘
外存:硬盘和U盘
内存与外存的区别
1)内存的存储空间比较小(8G,16G),外存的储存空间比较大(512G,1T)
2)内存的访问速度快,外存的访问速度慢(特指的是机器硬盘的物理结构,机器硬盘的物理结构,已经快十年没有发展过了)
3)内存的成本比较高,外存的成本比较高
4)内存中的数据,访问速度及其的慢,外存的数据,断电后还会存在;
3)输入设备:麦克风,键盘
4)输出设备:显示器

学的数据结构,之前写的代码,基本上都是保存在内存里面(代码中的变量,都是储存在内存里面)

客户端与服务器是通过网络来进行通信的,我们在客户端输入的每一条SQL语句,都会通过网络来构造请求传输给服务器;服务器会解析SQL里面的内容并执行,返回给服务器;

MYSQL的客户端和服务器可以在同一台主机,也可以在不同的主机;

咱们说的数据库是指在一个MYSQL服务器上面,所管理的一个独立的数据集合,在一个MYSQL服务器上面,可能有多个数据库

1)办公环境:入职的时候,公司会发一些电脑(台式本,笔记本,mac),也有少数公司,让自己带电脑;8核CPU,16G内存,512硬盘

2)开发环境/测试环境 一般是以服务器的形式来进行提供的,通过办公电脑通过网络远程的链接连接到你的服务器
16核CPU,64G内存,4T硬盘
有些项目跑起来是非常吃资源的,一进行启动内存,就吃掉几十个G,上百个G,用自己的把办公电脑可定是无法跑起来的;如果开发的程序比较小,这个时候就可能没有开发环境了,就直接使用办公电脑来进行开发;

3)线上环境,生产环境,也是以服务器的形式来进行提供的,也是通过办公电脑的网络远程连接上去;
56核CPU,256G内存,若干T硬盘,他是运行程序,给外边的用户来进行访问的,如果生产环境挂了,用户可能就会直接访问不了了;千万不能挂,每挂一分钟,公司可能就会造成大量的损失

2.MYSQL中所提供的数据类型

1)bit(位数)--char[]
2)tinyint--1个字节--byte
smalint--2个字节--short
int--四个字节---int
bigint--8个字节--long
3)float(A,B);4个字节
double(A,B);8个字节
这里面指定的数字是精度
A表示有效数字的长度,B表示小数的位数
decimal--表示更加精确的小数
4)varchar(字符个数)--表示字符串类型
MP3,png,.class文件都表示文本文件
txt,.java,.c都表示文本文件

4)日期类型
用varchar也可以表示日期类型,但是失去了对日期的校验功能;2022-03-08
datetime--8个字节
timestamp--4个字节
mysql> create table data(
    -> id int,
    -> time datetime);
 insert into data values(1,"2022-03-03");
 insert into data values(2,"2022-02-04 21:06:24");
 insert into data values(3,now());

2.基本操作

1)数据库的名字只能是数字字母下划线,不可以包含其他特殊符号;
2)创建重复的数据库,前面加if not exists,虽然也是可以执行的,但是不会创建新的数据库
3)使用数据库:use+数据库的名字
4)删除数据库:drop+database+数据库的名字
5)展示数据库show databases;在show databases中间还可以有空格,可以有一个,也可以有多个,不可以没有,SQL中的单词基本上是都是使用刻个来进行分割的,况且SQL语句是不会分成大小写的;
6)创建数据库:create+database+数据库的名字

1)创建表create table 表名(自定义类型名字+数据类型,自定义类型名字+数据类型);
2)查看表desc+具体的表名(查看表中都有哪些类型以及字段)
3)查看都有哪些表 show tables;
4)删除表 drop table+表名

一.向表中插入数据

1)insert into+表名+values(对应的字段内容),字段内容之间要用,来进行分开;values后面可以放多个括号,每一个括号对应一行,多个括号用,来进行分割;

create table student(
    -> id int,
    -> name varchar(20),
    -> score decimal(3,1),
    -> email varchar(50));
Query OK, 0 rows affected (0.03 sec)
插入表中的属性
insert into student values(1,"A",78.0,"[email protected]");
还可以这样进行插入
insert into student values(3,"C",78,"ddd"),(4,"D",89,"hhh");没有被插入的列会自动设置成false
字段与字段之间用,来进行分割
查看表中的数据:select * from+表名,*是一个通配符,意思是进行展示所有的数据
values后面的每一个括号都对应到一行,多个阔海之间用,来进行分割
1)要求values后面的字段的个数和表头约定的列数以及每一个列的类型要匹配
2)在SQL中,不区分字符串和字符

3)如果某一列是datetime,那么此时该如何进行插入操作呢?
1.通过指定固定格式的字符串来插入一个指定时间
2.通过now()函数来进行插入一个当前系统时间           

举一个插入时间的例子 

2)insert into +表名(属性一,属性二)+空格+values(与前面对应属性的字段),其他字段将采用默认值

注意:就算插入一列,这个大括号还是一定要有的,在进行插入的时侯,不管是几条,大括号都是一定要有的;

例如:insert into student (id) values(1),而不可以写成 insert into student id values(1);

1)insert into student(id,name)values(5,"E"),(6,"F");
2) insert into student(id,name,score)values(8,"H",89);
3) insert into student(id,name,score,email)values(9,"I",67,"123.com")(10,"J","69","139.com");

二:SQL查找

1)全列进行查找,直接把一张表中的所有行和列都进行查找出来

selext * from 表名

我们此时一定要注意:这种查询方式是把一个表中所有的行和列全部查询到,我们所查询到的结果是一个临时表,之前咱们所说的数据库中的表,都是在硬盘上面的,是持久化存在硬盘里面的;但是此时的这个查询结果临时表,不是在硬盘上面,而是在内存当中,随着进行输出的时候,数据也就被释放了

1)当用户输入sql之后,客户端就会把这条SQL语句包装成网络请求,发送给服务器;
2)服务器在收到请求之后,就会操作硬盘,从硬盘中读取数据,再把数据包包装成响应,响应的数据就是查询的结果;
3)客户端在收到这个响应数据之后,就会临时的把这个内存结果保存起来,并在显示器上面输出
4)随着打印完毕,客户端在内存中的保存的结果数据也就会被释放掉
况且select操作,是不会影响到服务器这边硬盘上面保存的数据

 但是select * from 表名,这样的操作其实是非常危险的,尤其是在线上环境下来进行这个操作;解析执行的过程,数据量很大,就意味着MYSQL服务器会疯狂读取硬盘数据,瞬间会把硬盘IO给吃满,硬盘的读取速度是存在上线的,尤其是机器硬盘;

同时MYSQL服务器,就会立即返回数据,由于返回的响应数据数据量很大很多,也会把网卡的带宽给吃满;(百兆网卡,千兆网卡,万兆网卡);

服务器就会变得非常忙,如果有其他的客户端来连接服务器,服务器就会无法响应;就难以对其他客户端的请求进行响应;用户可能会出现页面延迟;

2)指定列进行查询,在这里面会显示的告诉数据库要查询的是那些列,这样数据库就会有针对性地返回数据了

 create table student(
    -> id int,
    -> name varchar(20),
    -> chinese decimal(7,1),
    -> math decimal(6,1),
    -> english decimal(6,1));

查询所有同学的语文成绩加10; 

 3)根据字段指向别名

4.进行去重操作

select distinct chinese from student; 最好针对一个元素进行使用

5 排序,针对查询结果临时表进行排序(不会影响到源磁盘的数据)

asc是升序操作,desc是降序操作;

select 列名 表名 order by 列名 desc/asc;前面是降序,后面是升序

null+任何值都是null

1)先查找同学们的信息,再根据语文成绩进行升序排序 select * from student order by chinese desc;
2)按照总成绩进行升序排序
select id,name,chinese+math+english as total from student order by chinese+math+english asc;
3)根据多个列来进行排序
先根据第一个列来进行排序,如果第一个列结果相同,相同结果在根据第二个列来进行排序....
select * from student order by chinese,math,english;
这是先根据语文成绩进行升序排列,如果语文成绩相同,在按照数学成绩进行升序排列,如果数学成绩在相同,就按照英语成绩进行升序

1,=表示相等而不是赋值;
2,NULL=NULL结果还是空,会视为假;
3,<=>进行比较,他和=的用法是一致的,结果就是真NULL<=>NULL
4,between a and b,构成的是一个闭区间[a,b]
5,IN(),通过后面的()来进行指定一些值,判断当前结果是否在这几个值当中
6,is null,is not null;

6.按照条件进行查询--where,写上了条件之后,MYSQL在执行的时候就会进行条件筛选,遍历表中的每一条记录,带入到条件中,如果条件符合,就会把结果返回给客户端;不符合就会进行跳过;

1.查询数学成绩小于60分的同学
select * from student where english<60;
2 查找数学成绩大于语文成绩的同学·
select * from student where math>chinese;
3 查找总成绩低于200分的同学
select * from student where chinese+math+english<200;
4 查找数学成绩是空的同学
select * from student where math<=> null;
select * from student where math is null;
不可以写成这样
select * from student where math=null
5 查找语文成绩大于80英语成绩大于60分的同学
select name ,chinese+math+english as total where chinese>80 and english<60;
6 查找语文成绩大于60小于70之间的同学
select * from student where chinese>=60 and chinese<=70;
select * from student where chinese between 60 and 70;
7 查找数学成绩是45或者是70的同学
select * from student where math=45 or math=70;
select * from student where math in(45,70);

8.指定别名

 

小写字母变成大写字母 

这里我们要注意客户端显示的内容,select到where之间写的内容不会影响where之后的条件

表达式中如果同时有and和or那么就先计算and再对or进行计算,如果想要打破优先级,就需要加上and

select * from student from student where (chinese>80) or( math>70 and english>70);这样两个括号的条件满足一个就可以在屏幕上面进行展示了;

9.like通配符的形式来进行查找

模糊匹配,就相当于描述了一个规则;凡是符合这个规则的字符串,都会被匹配出来;

like操作通常要搭配通配符来进行使用
1)%匹配任意个字符
2)_匹配任意个字符

1))查找所有姓孙的同学 
select * from student where name like "孙%";
select * from student where name like "孙_";
2))查找所有语文成绩以9开头的同学
select * from student where chinese like"9%";
3))查找所有姓孙的同学并且语文成绩大于90的同学
select * from student where chinese>90 and name like "孙%";
如果写成%孙%,就意味着孙前面有着任意个字符,后面有着任意个字符
孙,孙aaa,aaa孙bbb,名字中包含孙即可

10.进行分页查询

在SQL中我们可以通过limit来实现分页查询
此时就可以约定好,一页当中最多显示多少个结果,在进行查找的时候,就可以根据页来进行返回,假设一页有20条记录;
第一页,就返回1-20
第二页,就返回21-40
第三页,就返回41-60
在SQL中,我们可以通过limit来实现分页查询
1)取我们进行查询结果的前三条
select * from student limit 3;只取出结果中的前三条
2)取我们结果中的4,5,6条记录
select * from student limit 3 offset 3;
3)我们来进行查询一下总成绩排名的前三名(注意order by是不可以和where进行在一起使用的
 select id,name,chinese+math+english as total from student order by chinese+math+english desc limit 3;
4)现在我们来查询一下总成绩排名的4-6名
select id,name,chinese+math+english as total from student order by chinese+math+english desc limit 3 offset 3;

 如何让SQL使用不在那么危险?

1)使用更严格的条件,where

2)使用limit来进行更稳妥的限制

三:SQL修改

注意:
1)insert和表名之间有一个into字段
2)select与表名之间有一个from
3)但是update与表名之间,啥也没有
另外,这里面的where和select中的where,用法是相同的,除了where之外,像order by和limit也是可以进行使用的
update是真的可以修改数据库服务器上面的原始数据的

核心操作:update+表名+set+列名=修改的值 where 条件(符合条件的行就会被修改,不符合条件的行就不会被修改,如果这里面的where省略了,就默认修改所有的行和列),这里面的列名可以有多个;

//注意:order by的使用要在from+表名之后
1)将A的语文成绩加10,下面两条是错误的
 update student chinese+10 where name="A";
 update student set chinese+10 where name="A";
正确的写法是update student set chinese=chinese+10 where name="A";
2)将B的语文成绩改成80,英语成绩改成40
update student set chinese=80,english=40 where name="B";
3)将所有人的语文成绩减10分,后面where不用添加任何条件
 update student set english=english-10;
4)将总成绩倒数后三名的同学的英语成绩减十分
关键的点有两个:1)首先要根据总成绩进行排序
2)再用limit来进行筛选前三
3)在对英语减10分
update student set english=english-10 order by chinese+math+english asc limit 3;
Matched:where语句匹配到了几行
Changed:真正的修改了几行

四.删除操作

delete from 表名 where 筛选条件
delete 后面没有*
如果这里面的筛选条件不一样,如果不写条件,或者是写错了,那么影响范围就会非常大,就会把整个表的数据都会给删除掉,但是表中的属性还在
他和drop table还是有一定的区别的,表没了,数据也没了;
这个就例如
ArrayList list=new ArrayList();
list.clear(),这个操作是将arraylist中的所有数据都给清空掉了;
list=null;把盒子和数据都给清空掉了
1)根据指定名字来进行删除
delete from student where name="A";
2)根据指定ID来进行删除
delete from student where id=3;
3)根据指定分数来进行删除
delete from student where chinese=118.1;

五.数据库的约束

自定义名字+数据类型+约束类型,例如id int not null;

数据库在使用的时候,对于里面的的所存数据提出的要求和限制;程序员就可以根据约束,对数据进行很好的校验;

下面说的限制,都是针对每一个列来单独进行设置的,只是针对这个列是这样的,不同的列之间是不会有影响的

1)not null表示某列不可以存储空值,如果尝试向着里面插入空值,就会发生报错;
2)unique必须保证唯一,如果尝试插入相同的数据,就会报错
3)default约定一个默认值,如果在进行插入的时候没有进行设置具体的值,就会自动被设成默认值,自动的默认值被设成kong;
4)primary key叫做主键约束,相当于是数据身份的唯一标识,相当于是身份证号码,手机号码
5)foreign key外键,描述两张表之间的关联关系,表一的数据必须在表二中存在
6)check这是指定一个条件,通过条件来对值进行判定,MYSQL不做支持
1)create table(id int not null,name varchar(20));当我们在尝试去插入元素的时候,就会插入失败;
mysql> insert into student values(null,"A");
ERROR 1048 (23000): Column 'id' cannot be null
not null是可以给任意一个列来进行设置非空,这是互不影响的
2)
mysql> create table student(
    -> id int unique,
    -> name varchar(20) not null);

mysql> insert into student values(1,"A");
Query OK, 1 row affected (0.01 sec)
mysql> insert into student values(1,"B");
ERROR 1062 (23000): Duplicate entry '1' for key 'id'
3)
 create table student(
    -> id int unique not null,
    -> name varchar(20) not null);
4)在MYSQL中,默认的默认值是空,在进行指定列插入的时候,其余的值会被自动的设成默认值,也就是空;
此处我们也可以把默认值转化成我们想要的值

Map里面存的是一个一个的键值对,Map里面又没有实现Iterable接口,所以要想遍历一个Map,就要先把Map转换成Set,Set里面的元素就叫做entry,里面就包含着一个键和一个值;

1)create table student(
    -> id int unique not null default "80",
    -> name varchar(20) default "like");
insert into student(id) values(1);
这个查询的结果就是id 变成1,name变成like
2)主键约束primary key相当于是unqiue和not null;
对于一张表来说,只能有一个列被指定成主键;
 create table student(
    -> id int primary key,
    -> name varchar(20) unique);

3)主键的一种特殊用法,自增主键,在primary key后面加上一个auto_increment,这就变成了一个自增主键;
create table student(
    -> id int primary key auto_increment,
    -> name varchar(20));
 insert into student values(null,"A"),(null,"B");
当我们设置好自增主键之后,此时我们所插入的记录,就可以不指定自增主键的值了(直接写成null),交给MYSQL自行处理即可;
+----+------+
| id | name |
+----+------+
|  1 | A    |
|  2 | B    |
+----+------+

但是要注意一点,自增主键也是可以自己手动指定id的,例如我写一条,insert into student values(10,"E");后续插入的数据只能是10以后的数据了,3-10中的数据就用不了了;

1)外键约束,针对两张表进行关联
学生(studentid,name,classID)
1 A java100
2 B java102

班级表(id,name)
1,java100;
2,java101;
3,java102;
这里面的每一个学生都有着自己的班级,这跟班级必须存在,如果这里出现了一个记录,这里的班级ID是10000,这个数据就是非法的;
学生表中的classID要依赖于班级表中的ID;
我们此时就把学生表称为子表,班级表称为父表;
 create table class(
    -> classID int primary key auto_increment,
    -> name varchar(20));

 insert into class values(null,"java100"),(null,"java101"),(null,"java102");
构建一个学生表,指定外键约束
 create table student(
    -> studentID int primary key auto_increment,
    -> name varchar(20),
    -> classid int,
    -> foreign key(classid) references class(classID));
外键约束一般是写在末尾,foreign key(在这个表中要指定的加上主键的列) references 另一张表的名字(需要关联的另一张表的列)
insert into student values(null,"A",1),(null,"B",2);这时就可以插入成功,因为学生的classid里面的值,在class表中的ClassID中已经存在
我们不仅仅在新增的时候要考虑到外键约束,在修改的时候也要考虑到外键约束,
在指定外键的时候,需要指定三方面
1)需要指定当前表中的那一列进行关联
2)需要指定和那张表进行关联
3)指定和目标表中的那一列进行关联
foreign key(属性1) references 目标表名(属性2)

所以说,外键约束描述的是两张表两个列之间的对应关系,子表要依赖于父表,要求子表中的数据必须在父表中存在;

 

 

当我们进行对student表进行插入的时候,MYSQL会先拿着classid到class表中的ClassID查询一下,看看是否存在,才可以插入成功;

但是我此时想要删除class表,也就是父表,可以删除成功吗?

delete from class where classID=2;这时候是无法进行删除的,外键约束是在同时约束着父表,当父表中的某条记录被子表依赖着的时候,此时如果再去尝试删除或者修改,都会失败,drop table class也是不可以的;

但是如果student表中的班级ID没有在class表中的班级ID出现过,此时就会可以进行删除;

外键约束的底层实现原理:在子表中插入新的记录的时候,就会先根据对应的值,在父亲表中进行查询,查询到之后,才可以进行后续的插入;

但是这里面的查询操作,可能是一个成本比较高的操作(在父亲表中进行查询是一个比较低效的操作,必须要有索引,有了索引之后才可以大大的提高效率;class表中的classID这一列,必须是primary key或者是unique,有了这两个条件之后,就会自动地构建出索引了;

一个父列可以约束多个子列,一个子列可以被多个父列所约束

设计数据库:造句法
一:一对一的关系:
拿教务系统为例
学生表(student):学生的ID,学生姓名,学生班级
用户表(user):用户的账号(13848061479),用户的密码
造的句子:一个学生对应到一个账户,一个账户只能对应到一个学生;
那么在数据库中如何表示这种一对一的关联关系呢?
1)可以把这两个实体用一张表来进行表示
2)user表中用一个userID,student表中可以有一个studentID,根据这个关系,就可以随时找到某个账户对应的学生是谁;某个学生对应到的账户是谁?
二:一对多的关系
student学生表(姓名,学号)
class表(班级编号,班级名称)
一个学生应该处于一个班级中,一个班级里面可以包含很多学生;
两种方法:班级表不变,在学生表里面,新增一列,叫做classID;
class: 班级编号 班级名称
         1      java100
         2      java101
student:学号 学生姓名  学生班级(classID)
       1 Lijiawei  1
       2 Lijiaxin  2
通过班级编号和学生的班级ID就巧妙地把学生和班级进行了关联

一个列,既可以是主键,又可以是外键;

多对多
学生表(学号,姓名)
课程表(课程编号,课程名字)
造句:一个学生,可以选择多个课程;一个课程,可以包含多个学生;
M个学生可以有N门课
在多对多的过程中,数据库设计就一招,使用一个关联表,来进行表示两个实体之间的关系
学生表:学号 姓名
        1   A
        2   B
课程表:编号  名称
        1   语文
        2   数学
创建一个关联表:学号 班级编号
               1      2
               1      3
这是说明学号是1的同学选择了班级编号是2的课程,课程编号为1的课程,包含了一个学号是1的同学;
通过第一列,就可以看出每个同学选择了那些课,通过第二列,就可以看出每个课上面有哪些同学

猜你喜欢

转载自blog.csdn.net/weixin_61518137/article/details/125027087