MYSQL操作详解

一)计算机的基本结构

 

 但是实际上,更多的是这种情况:

 

二)MYSQL中的数据类型:

 一)数值类型:

数据类型内存大小(字节)说明
bit(M)M指定位数,默认为1单个二进制位值,或者为0或者为1,主要用于开/关标志
tinyint1字节1个字节的整数值,支持0-255的整数
smallint2字节2个字节的整数值
int4字节表示4个字节的整数值
bigint8个字节
float(M,D)4个字节单精度浮点值,M指定长度,D表示小数位数
double(M,D)8个字节双精度浮点值,M指定长度,D表示小数位数
decimal(M,D)M/D+2定点或者精度可变的浮点值,M表示长度,D表示小数点位数
numeric(M,D)M/D+2

二)字符串类型:

sql中的字符串值可以用单引号也可以用双引号

数据类型大小说明
varchar0-65535字节可变长度字符串
text0-65535字节长文本数据

mediumtext

0-16 777 215字节中等长度文本数据
BLOB0-65,535字节二进制形式的长文本数据

三)日期数据类型

数据类型大小说明
datetime8个字节范围从1000-9999年
timestamp4个字节范围终止到2038年

MYSQL中表示日期:

1)dateTime:1753/1/1~9999/12/31

2)TimeStamp(2023年不够用)

3)字符串(用户自己写了一个日期,系统无法进行校验)

MYSQL插入时间:

1)调用NOW()方法进行插入

2)curdate();

3)curtime();

4)sysdate();

有关日期数据的插入,尽量使用datetime, 日期的插入格式为 : yyyy-mm-dd hh:mm:ss, 其中now()能够获取当前日期

三)数据库的基本操作:

create database Java200;
create database if not exists Java300;
create database Java400 charset utf8;
1)数据库的名字只能是数字字母下划线,不可以包含其他特殊符号,况且数据库名字不能是SQL中的关键字,如果非要使用,需要将关键字用反引号引起来关键字.
2)创建重复的数据库,前面加if not exists,虽然也是可以执行的,但是不会创建新的数据库,避免了sql语句批量执行时由于这一句报错而中断了后面的执行
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+表名

4)咱们在MYSQL中的代码表示钱有两种方式,第一种是使用Decimal/BigDecimal来进行表示还有就是使用int,单位是分

5)在MYSQL中创建列的时候,变量名是不能有-的,一般是使用_的

6)日常在cmd里面,使用ctrl+c来进行表示中断当前的输入,就是你的一个SQL输入一半,你不想要了,想重新进行输入,想要进行复制,就要先进行选中,然后enter建来进行复制

7)比如说像什么varchar(数字),长度具体是多少,产品经理都会有明确的规定的

一)向表中插入数据 

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,"156@.com");
还可以这样进行插入
insert into student values(3,"C",78,"ddd"),(4,"D",89,"hhh");没有被插入的列会自动设置成false
字段与字段之间用,来进行分割
查看表中的数据:select * from+表名,*是一个通配符,意思是进行展示所有的数据
values后面的每一个括号都对应到一行,多个字段之间用,来进行分割
1)要求values后面的字段的个数和表头约定的列数以及每一个列的类型要匹配
2)在SQL中,不区分字符串和字符,我们可以使用,也可以进行使用“
在咱们的JAVA中,""表示字符串,‘表示的是字符,但是在MYSQL中,是没有单独的字符类型
3)如果某一列是datetime,那么此时该如何进行插入操作呢?
1.通过指定固定格式的字符串来插入一个指定时间
2.通过now()函数来进行插入一个当前系统时间           

insert into student (id) values(1),而不可以写成 insert into student id values(1)

2)insert into +表名(属性一,属性二)+空格+values(与前面对应属性的字段)

其他字段将采用默认值

1)就算插入一列,这个大括号还是一定要有的,在进行插入的时侯,不管是几条,大括号都是一定要有的,大括号中的个数和类型要匹配

2)insert操作一次也是可以进行插入多个行,values后面的每一个()都对应着一行,可以一次性的带有多个(),多个()可以使用’,’来进行分割

3)一次进行插入N条记录的速度比一次插入一条,分N次进行插入,要快很多,因为实际上在客户端输入的每一条SQL都会通过网络传输给服务器,插入三条语句,就会构造出三条这样的请求,服务器每一次处理请求的时候,会进行解析请求中的SQL,执行里面的内容,并将响应返回给客户端;

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");
二)查询操作:
1)全列进行查找,直接把一张表中的所有行和列都进行查找出来

selext * from 表名,这里面的*表示通配符,可以匹配表中所有的列

1)此时一定要注意:这种查询方式是把一个表中所有的行和列全部查询到,我所查询到的结果是一个临时表,之前咱们所说的数据库中的表,都是在硬盘上面的

2)真实的数据是持久化存在硬盘里面的,但是此时的这个查询结果临时表,不是在硬盘上面,而是在内存当中,随着进行输出的时候,数据也就被释放了;

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

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

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

3)服务器就会变得非常忙,如果有其他的客户端来连接服务器,服务器就会无法响应;就难以对其他客户端的请求进行响应,用户可能会出现页面延迟,咱们生产环境的服务器是在无时无刻的在向普通用户提供响应的

4)在实际进行开发的时候,一般公司都会对SQL的执行时间进行长时间的监控,一旦出现了这种慢查询的SQL,就会强制的进行把这个SQL进行杀死;

2)指定列进行查询: 

1)在指定列查询的时候要显示的告诉数据库要查询的是那些列,这样数据库就会有针对性地返回数据了,查询的列不用加括号;

2)insert插入操作尤其是指定列插入一定要加上括号,哪怕只给一类插入数据,也要加上括号

3)这里查询结果所显示的表是服务器端数据库返回给客户端的一个临时表,使用查询操作不会对服务器中的数据造成影响, 该临时表在客户端打印后就销毁了;

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

3)还可以进行一些查询字段是表达式

3.1)就是说在我们进行Select查询的时候,同时进行一些运算操作,通常是列和列之间进行的运算

3.2)比如说:查询所有同学的语文成绩加10,加10操作只是对我们的临时表进行操作,也就是说这里面的查询结果变了,只是数据库服务器针对Select查询的结果进行了加工,把这些加工的数据作为临时表暂时显示出来了

​​

4)根据字段指向别名:相当于是给查询结果的临时表,指定一个新的列名,避免我们的得到的临时表,名字比较混乱,查询每一个同学的总分

select 列名或表达式 as 别名, ... from 表名;

1)总而言之,咱们上面的Select查询结果只是一个临时表,在客户端中临时保存的一个数据表,随着打印的进行,内存就被释放了,临时表的结果对咱们的原始数据没有任何影响

2)况且临时表的结果的数据类型不一定和原始的表的数据类型是完全一致的,比如说进行了相加操作,临时表的类型是会自动适应的,从而保证我们的计算结果是正确的,有效数字可能会发生变化,decimal;

3)比如说上面的+10操作,都是针对一个或者多个列来进行运算操作的,也就是说针对指定列中的每一行数据都会做相同的运算,计算总成绩的时候针对每一行的结果都进行相加,只是行和行之间不会有影响,列和列之间进行相加,才会有影响

  • 有null参与的运算最终的结果还是为null.
  • 每一个列或者表达式的别名只在当前字段有效, 如果运用到下一个字段就会报错
4)根据查询结果进行去重操作:针对查询的结果,把重复的记录给去掉

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

针对一列来进行去重:select distinct +列名+from+表名

针对多列来进行去重:select distinct+列名1,列名2+from+表名

在这里面要注意如果是根据多个列来进行去重,那么必须满足一个条件,就必须是多个列的值相同的时候才视为重复,

  • 去重查询只支持单列进行去重, 如果一次查询多列就会失去去重效果.
1)创建学生表:create table student(id int,name varchar(20),chinese decimal(3,1),math decimal(3,1),english(3,1));
2)插入数据:insert into student(id,name,chinese,math,english) values(1,"A",90,90,80),(2,"B",90,90.3,90.1),(3,"C",80,89,70);
3)指定列名进行查找:select name,chinese from student;
+------+------+---------+------+---------+
| id   | name | chinese | math | english |
+------+------+---------+------+---------+
|    1 | A    |    90.0 | 90.0 |    80.0 |
|    2 | B    |    90.0 | 90.3 |    90.1 |
|    3 | C    |    80.0 | 89.0 |    70.0 |
+------+------+---------+------+---------+
mysql> select distinct chinese from student;
+---------+
| chinese |
+---------+
|    90.0 |
|    80.0 |
+---------+
5)排序,针对查询结果临时表进行排序

不会影响到原磁盘的数据的顺序,它所影响的只是针对查询出来的临时表进行排序

select 列名, ... from 表名 order by 列名(要排序的列) asc(或者desc);

select 列名 from 表名 order by 列名 desc/asc;

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

2)desc是降序,asc是升序

3)null+任何值都是null,null和其他的值进行运算结果还是null

4)有的数据库记录中是带有NULL值的,像这样的NULL值就认为是最小的,升序就排在最前面,降序就自动排在最后面;

5)当排序指定多个列的时候,不是去将每一列单独进行排序,指定多个类属于复杂规则的比较,比如说指定的两个列,那么先以第一列的比较规则为准,如果第一列的比较比较不出来结果,那么再以第二列的规则去进行比较,以此类推;

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 id,name,chinese+math+english as total from student order by total;
4)根据多个列来进行排序
先根据第一个列来进行排序,如果第一个列结果相同,相同结果之间在根据第二个列来进行排序,select * from student order by chinese,math,english;
这是先根据语文成绩进行升序排列,如果语文成绩相同,在按照数学成绩进行升序排列,如果数学成绩在相同,就按照英语成绩进行升序,多个列进行排序的时候是明确优先级的

1)select * from student;
+------+------+---------+------+---------+
| id   | name | chinese | math | english |
+------+------+---------+------+---------+
|    1 | A    |    90.0 | 90.0 |    80.0 |
|    2 | B    |    90.0 | 90.3 |    90.1 |
|    3 | C    |    80.0 | 89.0 |    70.0 |
|    4 | D    |    10.0 | 78.0 |    80.0 |
|    5 | E    |    11.0 | 77.0 |    80.0 |
|    6 | F    |    11.0 | 79.0 |    60.0 |
+------+------+---------+------+---------+
6 rows in set (0.00 sec)
2)select id,name,chinese from student
 order by chinese desc;
+------+------+---------+
| id   | name | chinese |
+------+------+---------+
|    1 | A    |    90.0 |
|    2 | B    |    90.0 |
|    3 | C    |    80.0 |
|    5 | E    |    11.0 |
|    6 | F    |    11.0 |
|    4 | D    |    10.0 |
+------+------+---------+
3)select name,id,chinese+math+english as total 
from student order by chinese+math+english asc;
+------+------+-------+
| name | id   | total |
+------+------+-------+
| F    |    6 | 150.0 |
| D    |    4 | 168.0 |
| E    |    5 | 168.0 |
| C    |    3 | 239.0 |
| A    |    1 | 260.0 |
| B    |    2 | 270.4 |
+------+------+-------+
4)select name,id,chinese+math+english as total
 from student order by total asc;
+------+------+-------+
| name | id   | total |
+------+------+-------+
| F    |    6 | 150.0 |
| D    |    4 | 168.0 |
| E    |    5 | 168.0 |
| C    |    3 | 239.0 |
| A    |    1 | 260.0 |
| B    |    2 | 270.4 |
+------+------+-------+

select name,chinese+math+english as total from student order by (chinese+math+english as total) asc,这样的查询语句是错误的

select 列名 from 表名 order by 列名1 asc/desc,列名2 asc\desc,列名2 asc\desc

当我们的制定多个列来进行排序的时候,以第一列为主,第二列其次,当第一列的值相同的时候,才比较第二列,如果说最终第一列已经分出大小关系了,那么就不会比较后面的列了

最终的表显示什么,完全取决于select后面的列是怎么写的,写和不写不影响后面的条件,也就是说where后面的条件和咱们前面写的列没有任何关系

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

6)按照条件进行查询where

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

  1. where条件可以使用表达式,但不能使用别名
  2. and的优先级高于or,在同时使用时,需要使用小括号()包裹优先执行的部分
  3. 最终的表显示什么,完全取决于select后面的列是怎么写的,写和不写不影响后面的条件,也就是说where后面的条件和咱们前面写的列没有任何关系

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

  4. 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);
    
 7)指定别名:

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

2)现在来进行写一个SQL语句:

select * from student where chinese>80 or math>70 and english>70

执行结构就类似于这样:

select * from student where(chinese >80) or (math >70 and english>70)

想要显示这个结果的条件就是满足语文成绩大于80分或者数学和英语都大于70分的人

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

但是下面的这个写法就和上面完全不一样了:

select * from student where (chinese >80 or math>70) and english>70,这条语句的满足条件就是你这个人的语文后者数学成绩大于70并且你的英语成绩必须大于70

8)like通配符的形式来进行查找

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

查找所有名字中含有羊的同学:select * from user where username like "%羊%";

 insert into student(id,name) values(7,"G");
Query OK, 1 row affected (0.01 sec)

mysql> select * from student;
+------+------+---------+------+---------+
| id   | name | chinese | math | english |
+------+------+---------+------+---------+
|    1 | A    |    90.0 | 90.0 |    80.0 |
|    2 | B    |    90.0 | 90.3 |    90.1 |
|    3 | C    |    80.0 | 89.0 |    70.0 |
|    4 | D    |    10.0 | 78.0 |    80.0 |
|    5 | E    |    11.0 | 77.0 |    80.0 |
|    6 | F    |    11.0 | 79.0 |    60.0 |
|    7 | G    |    NULL | NULL |    NULL |
+------+------+---------+------+---------+
7 rows in set (0.00 sec)

mysql> select * from student where chinese=null;
Empty set (0.01 sec)

mysql> select * from student where chinese <=> null;
+------+------+---------+------+---------+
| id   | name | chinese | math | english |
+------+------+---------+------+---------+
|    7 | G    |    NULL | NULL |    NULL |
+------+------+---------+------+---------+
1 row in set (0.01 sec)

mysql> select * from student where chinese is null;
+------+------+---------+------+---------+
| id   | name | chinese | math | english |
+------+------+---------+------+---------+
|    7 | G    |    NULL | NULL |    NULL |
+------+------+---------+------+---------+
1 row in set (0.01 sec)

mysql> select * from student where chinese is not null;
+------+------+---------+------+---------+
| id   | name | chinese | math | english |
+------+------+---------+------+---------+
|    1 | A    |    90.0 | 90.0 |    80.0 |
|    2 | B    |    90.0 | 90.3 |    90.1 |
|    3 | C    |    80.0 | 89.0 |    70.0 |
|    4 | D    |    10.0 | 78.0 |    80.0 |
|    5 | E    |    11.0 | 77.0 |    80.0 |
|    6 | F    |    11.0 | 79.0 |    60.0 |
+------+------+---------+------+---------+
6 rows in set (0.00 sec)
like操作通常要搭配通配符来进行使用
1)%匹配任意个任意字符,包含0个字符
2)_匹配一个任意字符

1))查找所有姓孙的同学 
select * from student where name like "孙%";//此处我们这里面的孙%就可以匹配
任意以孙为开头的字符串,孙,孙########,但是匹配不到aaaa孙,aaa孙aaa
select * from student where name like "孙_";//孙坚,孙策,但是孙XXXX不能匹配

2))查找所有语文成绩以9开头的同学
select * from student where chinese like"9%";
3))查找所有姓孙的同学并且语文成绩大于90的同学
select * from student where chinese>90 and name like "孙%";

如果写成%孙%,就意味着孙前面有着任意个字符,后面有着任意个字符
孙,孙aaa,aaa孙bbb,名字中包含孙即可,如果写成aaaa就匹配不到
10)进行分页查询,order by的所在位置是在limit前面,limit是在最后面的

select 列名, ... from 表名 limit 限制个数 offset 起始下标;
select 列名, ... from 表名 limit 限制个数, 起始下标;

limit+n,取出已经读取数据结果中的前N条,他的效果就类似于limit+n+offset+0,意思就是说从我们查询结果的第0个位置开始,向后取N条记录

limit+n+offset+M,取出当前下标为N的记录开始,再向后找M条,默认从0开始,从我们查询结果的第M个位置开始,向后取N条记录

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

 现在来进行使用一下分页查询,根据每一位同学的总成绩显示结果,每一页有三条记录:

第一页:mysql> select name,chinese+math+english as total 
from student order by total desc limit 3 offset 0;
从我们查询结果的0号索引开始,向后取三条记录0-3
+------+-------+
| name | total |
+------+-------+
| B    | 270.4 |
| A    | 260.0 |
| C    | 239.0 |
+------+-------+
3 rows in set (0.00 sec)

第二页:mysql> select name,chinese+math+english as total
from student order by total desc limit 3 offset 3;
从我们查询结果的第三条记录开始,向取三条记录
+------+-------+
| name | total |
+------+-------+
| I    | 218.0 |
| H    | 210.0 |
| D    | 168.0 |
+------+-------+
3 rows in set (0.01 sec)

第三页:mysql> select name,chinese+math+english as total
 from student order by total desc limit 3 offset 6;
从我们查询结果的第六条开始,向后取3条记录
+------+-------+
| name | total |
+------+-------+
| E    | 168.0 |
| F    | 150.0 |
| G    |  NULL |
+------+-------+
3 rows in set (0.00 sec)

三)修改操作:

SQL修改:update+表名 set 列名=值,列名=值 where 条件

1)set关键字只需要写一次就可以了

2)多个修改恒等式中不要使用and,要使用,号来分割多个更新条件;

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

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

2)常见错误:

1)精度溢出:update student set chinese=chinese+10 where id<5;
ERROR 1264 (22003): Out of range value for column 'chinese' at row 1
2)语法记忆错误:
update student set chinese=chinese+1 and set english=english-1 where id<9;
update student set chinese=chinese-1,set english=english-2 where id<9;

但是下面这两个操作都是正确的:

1)mysql> update student set chinese=chinese-10 and english=english-10 
where id=1;
2)mysql> update student set chinese=chinese-10,english=english-5
 where id<7;
//注意: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:真正的修改了几行

1)当执行SQL语句进行操作数据库的时候,比如说:update student set chinese=chinese/2,这个是对所有的数据进行修改

2)这个时候的/2操作就会有可能发生警告,因为/2之后数据的位数就有可能超decimal(N,M)中的N位数,这时候有可能会发生数据溢出,通过show warnings就可以查看警告,Data truncated for column........,这就说明数据发生了截断

四)删除操作:

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)约束就是,数据库在使用的时候,对于里面的所存数据提出的要求和限制;

2)程序员就可以根据约束,对数据进行很好的校验,保证数据给符合咱们的需求和规范

3)在这里面所说的约束,都是针对每一个列进行设置的,不同的列之间是没有影响的

约束是关系型数据库的一个重要功能, 添加到库中的数据需要保证其的正确性;

约束, 就是让数据库帮助程序员更好的检查数据是否正确.

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

1)not null表示某列不可以存储空值,如果尝试向着里面插入空值,就会发生报错;
2)unique数据必须保证唯一,如果尝试插入相同的数据,就会报错(通过desc查看表就会发现key的一列变成了UNI)
3)default约定一个默认值,如果在进行插入的时候没有进行设置具体的值,
就会自动被设成默认值,自动的默认值被设成null;
4)primary key叫做主键约束,相当于是数据身份的唯一标识,相当于是身份证号码
手机号码,相当于是not null和unique的集合
5)foreign key外键,描述两张表之间的关联关系,表一指定列的数据必须在表二指定列中中存在
6)check这是指定一个条件,通过条件来对值进行判定,MYSQL不做支持

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

2)MYSQL是如何进行判断列是否是重复的呢?

这样的插入过程,其实就和咱们之前学过的二叉搜索树的插入过程是类似的,先要进行查找在进行插入

3)在MYSQL中,默认的默认值是空,在进行指定列插入的时候,其余的值会被自动的设成默认值,也就是空,此处也可以把默认值转化成我们想要的值就需要使用关键字default;

4)对于一张表来说,只能有一个列被指定为主键,primary key=not null unique

2)mysql> create table student(
    -> id int unique,
    -> name varchar(20) not null);
没有指定id列,其默认值为null,插入失败 
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);
1)create table student(id int not null,name varchar(20));当我们在尝试去插入元素的时候,就会插入失败;
mysql> insert into student values(null,"A");
ERROR 1048 (23000): Column 'id' cannot be null
inert into student(name) values("zhangsan”);
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);
 create table teacher(id int not null unique,name varchar(30) default "生命");
//not null和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中的数据就用不了了

create table teacher(id int not null unique,name varchar(30) default "生命");

mysql> desc teacher;
+-------+-------------+------+-----+---------+-------+
| Field | Type        | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| id    | int(11)     | NO   | PRI | NULL    |       |
| name  | varchar(30) | YES  |     | 生命    |       |
+-------+-------------+------+-----+---------+-------+
2 rows in set (0.01 sec)

外键约束:

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

2)foreign key(本表中所要父表中所依赖的列) references 父表的名字(引用的父表的列);

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中已经存在
我们不仅仅在新增的时候要考虑到外键约束,
在修改的时候也要考虑到外键约束
update student set classid=90 where studentID=1;------操作失败

在指定外键的时候,需要指定三方面
1)需要指定当前表中的那一列进行关联
2)需要指定和那张表进行关联
3)指定和目标表中的那一列进行关联
foreign key(属性1) references 目标表名(属性2)

要删除/修改的父表中的记录,前提是子表中没有记录与父表中的记录相关联

当子表中插入的记录和父表建立联系后此时就不能直接删除父表了要删除父表要先删除子表

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

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

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

3)但是如果student表中的班级ID没有在class表中的班级ID出现过,此时就会可以进行删除把class中的这个classID,对于子表来说不能乱插入或者修改,对于父表来说不能随便乱删除,必须保证这一列没有其他字表依赖才可以进行删除

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

4)但是这里面的内置的查询操作,可能是一个成本比较高的操作,在父亲表中进行查询是一个比较低效的操作,父表中所要依赖的这一列,必须要有索引,有了索引之后才可以大大的提高效率;

5)class表中的classID这一列,必须是primary key或者是unique,有了这两个条件之后,就会自动地构建出索引了;

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

1)现在有一个商品表,保存了商品信息:

商品ID 商品名字

1          苹果手机

2           涂改液

3           鼠标键盘

2)现在还有一个订单表,里面保存了订单信息

订单ID    商品ID

1                 1

2                 2

在上面描述的就是外健约束的关系,我们就可以认为商品表是父表,订单表就是子表,订单表中的ID应该在商品表中的ID存在

1)下好单子了,买了一个苹果手机,很久之后发现这个商品被下架了,从商品表中被删除了

2)那么这个数据是怎么删除的呢?按照刚才说的这个外健约束,一旦建立好了约束关系,那么父亲表的记录是不能够随便删除的,如果这个记录被子表依赖了,那么就无法删除了

第一种方案:

直接将订单表对应的记录进行删除,然后订单表中的订单ID不能出现在商品表中的商品ID,我们再进行删除对应的商品,先把订单表中的订单ID=1进行删除,然后再进行删除商品表中的订单ID=1的记录

第二种方案:但是正常来说订单是不应该被删除的,用户有权限查看自己的历史订单记录

重新建立一个不被约束的订单表,删除原记录

第三种方案:

在这里面删除的方法是,并不是真的删除,而是采用一种逻辑上的删除,我们给商品表增加一个列,如果这个列是1,那么表明这是一个有效记录,如果这一列是0,那么就表示这是一个无效记录;

后续在进行条件查询商品信息的时候,直接将IsOK=0的商品信息全部过滤掉就可以了,只保留isOK=1,也不会打破子表和父表之间的外健约束

如果不是真的删除而是逻辑上进行删除的话,这个记录不就会始终存在吗?这不就会导致数据库里面的内容越来越多,逐渐膨胀,不是十分浪费磁盘空间吗?

磁盘空间不值钱,远远不如人力成本高

那么我们如何进行设计数据库,如何进行设计表呢?

一个典型的通用的办法就是先找出这个场景中所对应到的实体再来具体分析实体之间的关系,实体也被称之为JAVA中的对象,实体就是可以视为需求中一些关键性的名词;

现在有一个具体的场景:

学生管理系统:

1)表示学生的基本信息

2)表示班级的基本信息

3)表示学生所学的课程的基本信息

 一对一:

设计数据库:造句法
一对一的关系:
拿教务系统为例
学生表(student):学生的ID,学生姓名名字,学生班级名字
用户表(user):用户的账号(13848061479),用户的密码
造的句子:一个学生对应到一个账户,一个账户只能对应到一个学生,一个账户不能被多个学生所共有,一个学生也不能有多个账户;
那么在数据库中如何表示这种一对一的关联关系呢?

1)可以把这两个实体用一张表来进行表,我们直接用一张表把这两张表的信息全部表述出来
2)可能用两张表来进行表示,其中一张表包含了另一张表的ID,user表中用一个userID,student表中可以有一个studentID,根据这个对关系,就可以随时找到某个账户对应的学生是谁,某个学生对应到的账户是谁

一对多:


student学生表(姓名,学号)
class表(班级编号,班级名称)
一个学生应该处于一个班级中,一个班级里面可以包含很多学生;

第一种方法:在班级表里面新增一列,表示这个班级里面的学生ID都有啥?
通过这种方式就可以进行表示一个班级都对应着那些同学

像MYSQL没有数组类型,但是像Redis这样的数据库,就有数组类型


第二种方法:班级表不变,在学生表里面,新增一列,叫做classID;
通过班级编号和学生的班级ID就巧妙地把学生和班级进行了关联,通过这种方式也能知道一个班级对应着那些同学


 

多对多:
学生表(学号,姓名)
课程表(课程编号,课程名字)
造句:一个学生,可以选择多个课程,一个课程,可以包含多个学生;
M个学生可以有N门课
在多对多的过程中,数据库设计就一招,使用一个关联表,来进行表示两个实体之间的关系

五)高级查询:

1)和查询结合在一起的新增操作

中心思想:把从上一个表中的查询结果,作为下一个表中要插入的数据

1)现在先创建一个表A,里面两列是字符串和整数,此时也要进行创建表B,分配字段名,保证第一列是字符串,第二列是整数,这样才可以保证A的记录成功的被导入到B里面了

2)insert into B  select * from A,这个操作就是说先执行查找,在A里面进行查找,针对进行查找到的每一条结果插入到B里面;

drop table student;
mysql> create table student(id int,name varchar(40));
drop table teacher;
mysql> create table teacher(userID int,username varchar(40));
1)insert into student values(1,"A"),(2,"B"),(3,"C");
2)insert into teacher select * from student;
3)select * from student;
+--------+----------+
| userID | username |
+--------+----------+
|      1 | A        |
|      2 | B        |
|      3 | C        |
+--------+----------+
4)select * from teacher;
+--------+----------+
| userID | username |
+--------+----------+
|      1 | A        |
|      2 | B        |
|      3 | C        |
+--------+----------+

当表中的列的顺序和我们已经写好的标的顺序不一样的时候,我们也是可以进行插入的
 create table Test(username varchar(50),id int);
这么写是不行的:
 insert into Test select * from student;
ERROR 1366 (HY000): Incorrect integer value: 'A' for column 'id' at row 1
可以这么写:所以我们就可以通过指定列查询的方式,保证我们查询结果的顺序可以和Test对上:
 insert into Test select name,id from student;
mysql> select * from Test;
+----------+------+
| username | id   |
+----------+------+
| A        |    1 |
| B        |    2 |
| C        |    3 |
+----------+------+

1)create table TestDemo(username varchar(40),userID int,password varchar(40));
2)insert into TestDemo(username,userID) select name,id from student;
3)select * from TestDemo;
+----------+--------+----------+
| username | userID | password |
+----------+--------+----------+
| A        |      1 | NULL     |
| B        |      2 | NULL     |
| C        |      3 | NULL     |
+----------+--------+----------+

1)总而言之,select指定一些其他的条件例如说排序,去重,limit操作都是可以的,我们实际上插入的就是select执行结果的临时表,是把查询的结果是在临时表里面的,是把临时表的数据插入到数据库服务器的硬盘里面了insert修改的是硬盘的数据

2)将表a中的数据插入到表b,实质上是先查询a表中的数据生成临时表,再将临时表中的数据插入表中,要注意的是查询出来的记录(临时表)的列需要和表b相对应的列数据类型相同才能插入成功.

2)聚合查询(把多个相同字段的列放在一起):

本质上来说就是把多行的数据给聚合到一起了,之前咱们查询带有表达式的操作,这个是属于列和列之间的运算

常见的聚合函数:

查看有多少行:

下列四种聚合函数不是针对数字没有意义

1)null的值是不会记录到count(Chinese)中了,但是计算count(*)的时候会进行计算

2)sum只能针对数字进行运算,不可以用于字符串之间的运算

MYSQL中内置了一些聚合函数让我们直接进行使用
1)查找数据库中有多少行
select count(*) from student;
上面的这个操作就是先进行select * from student,再来进行查询结果有多少行
2)查找名字有多少行,查找语文成绩有多少行?
select count(id) from student;
select count(name) from student;
select count(chinese) from student;
3)求和sum(字段)
 select sum(chinese) from student;//查找语文成绩的总和
 select sum(math) from student;
 select sum(english) from student;
这些聚合函数是针对一个或多个列的行来进行运算的, 其中sum,avg,max,min这几个聚合函数只能针对数值类型进行计算,,不能是字符串和日期类型;
聚合函数还可以针对搭配where语句来进行使用
比如说我们进行查找所有英语成绩大于70分的同学的总和
select sum(english) from student where english>70;
形如这样的操作,会先执行条件筛选,再去执行聚合操作
select sum(chinese)+sum(english) from student;
select sum(chinese+math+english) from student;
1)查找语文成绩的平均分
select avg(chinese) from student;
2)查找所有语文成绩分数小于90的平均分
select avg(chinese) from student where chinese<90;
3)求最大值
select max(chinese) from student
1)create table student (userID int,username varchar(70),chinese int, math int,english int);
2)insert into student values(1,"A",90,89,80),(2,"B",70,30,80),(3,"C",80,77,60),(4,"D",70,89,60),(5,"E",70,88,100);
3)insert into student values(6,"H",null,null,99);
4)select * from student;
+--------+----------+---------+------+---------+
| userID | username | chinese | math | english |
+--------+----------+---------+------+---------+
|      1 | A        |      90 |   89 |      80 |
|      2 | B        |      70 |   30 |      80 |
|      3 | C        |      80 |   77 |      60 |
|      4 | D        |      70 |   89 |      60 |
|      5 | E        |      70 |   88 |     100 |
|      6 | H        |    NULL | NULL |      99 |
+--------+----------+---------+------+---------+
5)select distinct count(chinese) from student;
+----------------+
| count(chinese) |
+----------------+
|              5 |
+----------------+
6) select count(chinese)+count(math) from student;
+----------------------------+
| count(chinese)+count(math) |
+----------------------------+
|                         10 |
+----------------------------+
7)> select sum(chinese+english+math) from student;
+---------------------------+
| sum(chinese+english+math) |
+---------------------------+
|                      1133 |
+---------------------------+
8)select sum(chinese) from student where chinese>100;
+--------------+
| sum(chinese) |
+--------------+
|         NULL |
+--------------+

 创建一个学生表插入数据,进行函数查询

create table result (
         id int,
         name varchar(20),        
       chinese decimal(4, 1),       
       math decimal(4, 1),       
       english decimal(4, 1));
insert into result values
     (1, 'A', 67, 98, 56),
     (2, 'B', 87.5, 78, 77),
     (3, 'C', 88, 98.5, 90),
     (4, 'D', 82, 84, 67),
     (5, 'E', 55.5, 85, 45),
     (6, 'F', 70, 73, 78.5),
     (7, 'G', null, 75, 65),
     (8, null, null, 75, 65);

1)计算所有同学语文成绩的总和

select sum(chinese) from result

2)统计英语成绩不及格同学(<60)成绩的总和

select sum(english) from result where english<60;

3)统计所有同学总分的平均分

select avg(chinese+math+english) from result

4)统计英语最高分

select max(english) from result

5)统计70 分以上的数学最低分

select min(math) from result where math>=70

3)分组操作:group by根据行的值,对数据进行分组,把值相同的行都归成一组,不同的值就存放在不同的组里面

 create table HH(
     id int primary key auto_increment,
     name varchar(20),
     role varchar(20),
     salary decimal(7,1));
 insert into HH values(null,"E","teacher",3000.3),(null,"B","doctor",4000.2),(null,"C","teacher",5000.7);

1)需要来进行查询,要查找每一个角色的最高工资,最低工资和平均工资,那么这种角色我们就需要按照岗位来进行分组

2)group by role,这种写法就是把角色进行分组,把teacher,放在一组,里面有A,E,C;把doctor放在一组,里面有B,S;把所有的leader放在一组,里面有O和J;

1)先根据group by按照role来进行分组

2)再次执行聚合函数,针对咱们分出来的每一个组来进行求最大值,最小值,还有平均值

3)咱们SQL的执行顺序并不是按照咱们写的顺序来进行执行的

select role,max(salary),min(salary),avg(salary) from HH group by role

from前面是最终展现的结果;后面实质上是先分成了三个组,并针对每一个组来进行求最大值,最小值,平均值;

先执行group by进行分组,再去针对每一个组,来进行聚合查询函数,也可以进行指定别名:

select role,max(salary) as max,min(salary) as min,avg(salary) from HH group by role

咱们实际上可以先画图,根据group by来进行分组,再来进行执行聚合函数

1) create table TestData(userID int primary key auto_increment,username varchar(60),role varchar(80),salary int);
2)insert into TestData values(null,"A","老师",9000),(null,"B","老师",9003),(null,"C","程序员",10000),(null,”D","程序员",10000);
3) insert into TestData values(null,"I","领导",10007),(null,"R","领导",6000),(null,"K","老师",7000),(null,"O","程序 员",10000);
4) select * from TestData;
+--------+----------+-----------+--------+
| userID | username | role      | salary |
+--------+----------+-----------+--------+
|      1 | A        | 老师      |   9000 |
|      2 | B        | 老师      |   9003 |
|      3 | C        | 程序员    |  10000 |
|      4 | D        | 程序员    |  10000 |
|      5 | I        | 领导      |  10007 |
|      6 | R        | 领导      |   6000 |
|      7 | K        | 老师      |   7000 |
|      8 | O        | 程序员    |  10000 |
+--------+----------+-----------+--------+
5)select role,avg(salary),max(salary),min(salary) from TestData group by role;
+-----------+-------------+-------------+-------------+
| role      | avg(salary) | max(salary) | min(salary) |
+-----------+-------------+-------------+-------------+
| 程序员    |  10000.0000 |       10000 |       10000 |
| 老师      |   8334.3333 |        9003 |        7000 |
| 领导      |   8003.5000 |       10007 |        6000 |
6) select role,salary from TestData group by role;
+-----------+--------+
| role      | salary |
+-----------+--------+
| 程序员    |  10000 |
| 老师      |   9000 |
| 领导      |  10007 |
+-----------+--------+
这么写的话只会针对第一次出现的工资进行显示

因为我们是在分组之前进行指定的条件,所以我们需要把这个where条件写在group by之前

如果我们是在分组之后进行指定的条件,所以我们需要把having加入到group by的后面

1)分组之前指定条件:去掉A这个角色,再去求每一组角色的薪资的平均值:

 select role,avg(salary),max(salary),min(salary) from TestData
 where username!="A" group by role;
+-----------+-------------+-------------+-------------+
| role      | avg(salary) | max(salary) | min(salary) |
+-----------+-------------+-------------+-------------+
| 程序员    |  10000.0000 |       10000 |       10000 |
| 老师      |   8001.5000 |        9003 |        7000 |
| 领导      |   8003.5000 |       10007 |        6000 |
+-----------+-------------+-------------+-------------+

2)分组之后指定条件,求出每一种职业的平均薪资大于9000以上的:


mysql>  select role,avg(salary),min(salary) from TestData group by role having avg(salary)>9000;
+-----------+-------------+-------------+
| role      | avg(salary) | min(salary) |
+-----------+-------------+-------------+
| 程序员    |  10000.0000 |       10000 |
+-----------+-------------+-------------+

1)先根据group by来进行分组

2)再求出聚合函数,求出每一组的平均薪资,最小薪资

3)再根据having对分组之后算出的聚合函数再进行筛选,平均薪资大于9000的被保留

再来写一个SQL,把用户K和O去掉,求每一类职业的平均值大于8000的

select role,avg(salary) from TestData where username!="K" and username!="O" group by role having avg(salary)>8000;
+-----------+-------------+
| role      | avg(salary) |
+-----------+-------------+
| 程序员    |  10000.0000 |
| 老师      |   9001.5000 |
| 领导      |   8003.5000 |
+-----------+-------------+
1)先根据where指定条件进行筛选,这是分组前的筛选,把K和O去掉
2)根据group by进行筛选,把角色相同的分成一组
3)进行聚合查询,求出平均工资
4)再根据分组后的工资进行筛选(having)

进行avg的时候,NULL这样的记录是不会记录在其中的,是不会影响到平均值这样的结果的

2)现在再去查询,查询出所有平均工资高于4000的工作岗位

2.1)进行分组之后要对结果进行条件筛选,就要用到having

2.2)想要针对分组之前,想要查询结果,我们可以通过where来进行指定条件

这里一定要注意where和group by两者的区别
having是针对group by之后的结果进行筛选
where是针对原始数据表中的每一条记录都会进行筛选
下面来举个例子:
1)分组之前进行条件筛选:也是求每种角色的平均薪资,但是要去掉A,
这是分组之前所指定的条件,就需要使用where
select role,avg(salary) from HH where name!="A" group by role ;
去掉A并且去掉E
 select role,avg(salary) from HH where name!="A" 
and name!="E" group by role;
这里一定要注意:where要写在group by 前面,having要写在group by后面

2)分组之后再去进行条件筛选:求每种角色的平均薪资,
只保留平均薪资在4000以下的角色,在这里面就要先进行分组计算
知道了各个岗位的平均薪资之后才可以进行筛选;
select role,avg(salary) from HH 
group by role having avg(salary) >4000;
 select avg(salary) from HH group by role having avg(salary)>4000;
4)联合查询(把多张表组合在一起,多表查询,多个表的记录是放在一起的)

3.1)笛卡尔积,多表查询的核心操作,非常类似于排列组合,它是针对任意两张表进行运算;

3.2)中心思想就是拿第一张表的第一条记录,和第二张表的每一条记录分别进行组合,这样就得到了一组新的记录,我们再拿第一张表的第二条记录,分别于第二张表的第一条,第二条进行组合

学生表(studentID,name,classID)
          1     张三    1
          2     王五    1
          3     李四    2
          4     赵六    2
班级表(classID,name)
        1      java100
        2      java101
        3      java102
进行笛卡尔积之后,得到的结果就类似于这样:
studentID name classID classID  name
  1     张三    1 1      java100
  1     张三    1 2      java101
  1     张三    1 3      java102
  2     王五    1 1      java100
  2     王五    1 2      java101
  2     王五    1 3      java102
  3     李四    2 1      java100
  3     李四    2 2      java101 
  3     李四    2 3      java102
那么此时A,B两张表进行笛卡尔积运算的时候,此时笛卡尔积的行数,就是A的行数*B的行数;笛卡尔积的列数就是A的列数+B的列数;如果A,B两张表都很大,就有可能把数据库给搞挂了

1)那么在SQL中如何进行笛卡尔积的操作呢?(表明之间使用,进行分割)

select 显示的字段+from+表名1,表名2;

select * from student,class

2)查询同学对应的班级

1)现在要查询学生与对应的班级名字,上面的笛卡尔积是一个无脑的排列组合这里面的排列组合不一定都是有意义的数据

2)咱们使用多表查询之前是否应该是用一下count(*)来看看数据的范围呢?

这个是不行的,因为数据的变化是在随时变动的,你也无法确定一段时间内有多少用户被插入到了你的数据库里面

3)上述过程中的多表查询,学生表中的ClassID和班级表中的ClassID相同的信息记录才是我们最终要保留的记录;

直接from一张表,后面写表名,from 表1 join 表2 on 条件
select student.name,score.score from student join score on student.id=score.student_id and name="A";
from 表1,表2 where 条件

1)where语句之前是要展示的数据,表名.列名(属性),况且如果笛卡尔积中的两个列名字相同,就可以通过表名.列名的方式来进行访问,如果列名没有重复,那么也是可以通过表名.列名的方式进行访问,此时也是可以进行省略表名的

2)我们在最终的查询结果中,一般只是需要部分列来进行显示,想要哪个列就可以通过表名.列名的方式来进行显示这一行就行了; 

drop table if exists classes;
drop table if exists student;
drop table if exists course;
drop table if exists score;

create table classes (id int primary key auto_increment, name varchar(20), `desc` varchar(100));

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

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

create table score(score decimal(3, 1), student_id int, course_id int);

insert into classes(name, `desc`) values 
('计算机系2019级1班', '学习了计算机原理、C和Java语言、数据结构和算法'),
('中文系2019级3班','学习了中国传统文学'),
('自动化2019级5班','学习了机械自动化');

insert into student(sn, name, qq_mail, classes_id) values
('09982','黑旋风李逵','xuanfeng@qq.com',1),
('00835','菩提老祖',null,1),
('00391','白素贞',null,1),
('00031','许仙','xuxian@qq.com',1),
('00054','不想毕业',null,1),
('51234','好好说话','say@qq.com',2),
('83223','tellme',null,2),
('09527','老外学中文','foreigner@qq.com',2);

insert into course(name) values
('Java'),('中国传统文化'),('计算机原理'),('语文'),('高阶数学'),('英文');

insert into score(score, student_id, course_id) values
-- 黑旋风李逵
(70.5, 1, 1),(98.5, 1, 3),(33, 1, 5),(98, 1, 6),
-- 菩提老祖
(60, 2, 1),(59.5, 2, 5),
-- 白素贞
(33, 3, 1),(68, 3, 3),(99, 3, 5),
-- 许仙
(67, 4, 1),(23, 4, 3),(56, 4, 5),(72, 4, 6),
-- 不想毕业
(81, 5, 1),(37, 5, 5),
-- 好好说话
(56, 6, 2),(43, 6, 4),(79, 6, 6),
-- tellme
(80, 7, 2),(92, 7, 6)

创建表操作:
1)创建学生表create table student(
   id int primary key auto_increment,
    student_id varchar(20),
    name varchar(20),
   qq_mail varchar(20),
    class_id int);

2)创建班级表 create table class(
      classID int,
      name varchar(20),
      about varchar(30));

3)创建课程表 create table course(
       courseID int primary key auto_increment,
      name varchar(20));
Query OK, 0 rows affected (0.03 sec)

4)创建分数表
create table score(
score int,
studentID int,
course_id int);
插入:
1)向学生表里面插入数据 insert into student values(1,"202110201001","A","131.com",1),(2,"202110201002","B","132,com",1),(3,"202110201003","C","133.com",1),(4,"202110201004","D","135.com",1),(5,"202110201005","E","136.com",1);
insert into student values(6,"202110201006","F","137.com",2),(7,"202110201007","G","138.com",2),(8,"202110201009","H","139.com",2);
2)像班级表里面插入数据
  insert into class values(1,"Java100","very nice"),(2,"java101","very rubblish"),(3,"java102","nice");
3)向课程表里面插入数据
insert into course values(1,"chinese"),(2,"math"),(3,"english");
4)向分数表中插入数据
insert into score values(71,1,1),(99,1,3),(33.0,1,5),(98.0,1,6),(60.0,2,1),(59.5,2,5),(33.0,3,1),(68.0,3,3),(99.0,3,5),(67.0,4,1),(23.0,4,3);

在这个场景中,学生和班级是一对多的关系,学生与课程是多对多的关系

分数表存在的意义不仅仅是为了表示分数,而且还是学生与课程之间的关联表

例题1:查找A同学的成绩,查看学生对应的分数信息
我们知道:同学A学了很多课,我们就需要在学生表中获取到学生姓名,在分数表中获取到分数信息;
分析这样的问题,一定要知道想清楚要查询的信息在哪些表里面;把学生表和分数表进行笛卡尔积
select * from student,score where score.studentID=student.id;
select * from student,score where score.studentID=student.id and name="A";
having是搭配group by进行使用的

1)当前咱们的笛卡尔积记录太多, 仔细观察就可以发现,在我们的学生表和分数表里面,都存在着有关于学生ID这一列

2)按照咱们之前总结的规律,应该将这两个学生ID进行匹配,才会进行保存对应的记录,这两张表中的学生ID不相等的列咱们就会视为无效记录

 

先分析数据是来自于那些表,然后再进行笛卡尔积,观察笛卡尔积的结果,筛选出合法的数据,在逐步地根据需求,添加新的条件,让数量一点一点地接近预期,最后把整个列在进行筛选;

查看所有同学所选课程对应的成绩
1)select student.name,course.name,score.score from student,course,score where student.id=score.studentID and score.course_id=course.courseID;
+------+---------+-------+
| name | name    | score |
+------+---------+-------+
| A    | chinese |    71 |
| A    | english |    99 |
| A    | Java    |    33 |
| A    | C++     |    98 |
| B    | chinese |    60 |
| B    | Java    |    60 |
| C    | chinese |    33 |
| C    | english |    68 |
| C    | Java    |    99 |
| D    | chinese |    67 |
| D    | english |    23 |
+------+---------+-------+
查看A同学所选课程对应的成绩

2)select student.name,course.name,score.score from student,course,score where student.id=score.studentID and score.course_id=course.courseID and student.name="A";
+------+---------+-------+
| name | name    | score |
+------+---------+-------+
| A    | chinese |    71 |
| A    | english |    99 |
| A    | Java    |    33 |
| A    | C++     |    98 |
+------+---------+-------+

1)进行多个条件的筛选过程中where后面的条件可以用多个and来进行分割

2)select 列名1,列名2  from 表名1 join 表名2 on 条件

from 一张表 join 另一张表 on 条件,它还实现了from无法实现的功能

2)查询所有同学的总成绩,以及同学的个人信息(同学名字)
我们不光要查询出同学的名字,还要查询课程的名字,还有课程的分数

这个案例要在多表查询的基础上加上聚合查询;
我们先去查询所有同学的总成绩,根据学生的id来进行分组;
select name,score.score from student join score on
 score.studentID=student.id;
select name,score.score from student join score on
 score.studentID=student.id;
+------+-------+
| name | score |
+------+-------+
| A    |    71 |
| A    |    99 |
| A    |    33 |
| A    |    98 |
| B    |    60 |
| B    |    60 |
| C    |    33 |
| C    |    68 |
| C    |    99 |
| D    |    67 |
| D    |    23 |
+------+-------+
select name,sum(score.score) from score,student
 where score.studentID=student.id group by student.name;
+------+------------+
| name | sum(score) |
+------+------------+
| A    |        301 |
| B    |        120 |
| C    |        200 |
| D    |         90 |
+------+------------+

3)查询所有同学的成绩和同学的相关信息;
同学名字 学生表
课程名字 课程表
分数     分数表
insert into course values(4,"history"),(5,"bilology"),(6,"water");
select * from student,course,score
 where student.id=score.studentID and
 course.courseID=score.course_id;
在进行这个查询之后,我们就列出了每一个同学每一个课程拿到的分数,同时带有课程的名字

下一步要做的就是去掉不必要的列,只保留所关注的关键列,学生姓名,课程姓名分数

select student.name,course.name,score.score from student,course,score where student.id=score.studentID and course.courseID=score.course_id;

1)select student.name,course.name,score.score from student join score on student.id=score.studentID join course on course.courseID=score.course_id;
2)select 列名1,列名2 from 表1 join 表2 on 条件 join 表3 on 条件

join on还有一些其他的用法

上面说的from多个表叫做内连接,使用join on既可以表示内连接,又可以表示外连接;
select 列 from 表1 inner 表2 on 条件   
select 列 from 表1 left  join 表2 on 条件; 左外连接
select 列 from 表1 right join 表2 on 条件; 右外连接

     create table student(
     id int,
     name varchar(20),
     classID int);

     create table class(
     id int,
     name varchar(20));
insert into student values(1,"A",1),(2,"B",1),(3,"C",2),(4,"D",3),(5,"E",4);
insert  into class values(1,"java100"),(2,"java101"),(3,"java102");

mysql> select * from student;          
+------+------+---------+
| id   | name | classID |
+------+------+---------+
|    1 | A    |       1 |
|    2 | B    |       1 |
|    3 | C    |       2 |
|    4 | D    |       3 |
|    5 | E    |       4 |
+------+------+---------+
5 rows in set (0.00 sec)

select * from class;
+------+---------+
| id   | name    |
+------+---------+
|    1 | java100 |
|    2 | java101 |
|    3 | java102 |
+------+---------+

1)但是我们在上面发现student表中有一条为班级ID为5的记录,但是在我们的class表中,并没有id为5的记录(没有一个班级ID=5);此时如果进行联合查询,就会出现问题;

mysql> select * from student,class where student.classID=class.id;
+------+------+---------+------+---------+
| id   | name | classID | id   | name    |
+------+------+---------+------+---------+
|    1 | A    |       1 |    1 | java100 |
|    2 | B    |       1 |    1 | java100 |
|    3 | C    |       2 |    2 | java101 |
|    4 | D    |       3 |    3 | java102 |
+------+------+---------+------+---------+
此时上面的学生表中的id=5记录就消失了

2)现在进行内连接或者是普通的笛卡尔级运算的操作,此时我们就发现,这里面明显少了一条id=5的同学的记录的

  此时改成左外连接:select * from student left join class on student.classID=class.id;

 select * from student left join class on student.classID=class.id;
+------+------+---------+------+---------+
| id   | name | classID | id   | name    |
+------+------+---------+------+---------+
|    1 | A    |       1 |    1 | java100 |
|    2 | B    |       1 |    1 | java100 |
|    3 | C    |       2 |    2 | java101 |
|    4 | D    |       3 |    3 | java102 |
|    5 | E    |       4 | NULL | NULL    |
+------+------+---------+------+---------+

1)通过刚才的例子,我们可以看出left join和inner join的区别,inner join这里面就要求的是两张表里面同时都有的数据(都有classID),才最终会显示在屏幕上;

left join以左侧的表为主,左侧表中的数据都能够在最终的表中显示出来,大不了对应的右侧的表数据填空

2)right的作用也是类似,是以右侧的表为主,尽可能把右侧的记录都列出来,在最终的表中有体现,大不了对应的左侧的表都填成null;

3)此时如果改成右外连接:select * from student right join class on student.classID=class.id;就会发现,此时又变成了四条;

     create table student(
          id int,
        name varchar(30));

       create table score(
       studentID int,
       score int);
       insert into student values(1,"A"),(2,"B"),(3,"C");
       insert into score values(1,90),(2,80),(4,70);
1)查看表结构:
mysql> select * from student;
+------+------+
| id   | name |
+------+------+
|    1 | A    |
|    2 | B    |
|    3 | C    |
+------+------+
3 rows in set (0.00 sec)

mysql> select * from score;
+-----------+-------+
| studentID | score |
+-----------+-------+
|         1 |    90 |
|         2 |    80 |
|         4 |    70 |
+-----------+-------+
3 rows in set (0.00 sec)
1)进行左连接:
mysql> select * from student left join score on student.id=score.studentID;
+------+------+-----------+-------+
| id   | name | studentID | score |
+------+------+-----------+-------+
|    1 | A    |         1 |    90 |
|    2 | B    |         2 |    80 |
|    3 | C    |      NULL |  NULL |
+------+------+-----------+-------+
3 rows in set (0.00 sec)

2)进行右连接:
 select * from student right join score on score.studentID=student.id;
+------+------+-----------+-------+
| id   | name | studentID | score |
+------+------+-----------+-------+
|    1 | A    |         1 |    90 |
|    2 | B    |         2 |    80 |
| NULL | NULL |         4 |    70 |
+------+------+-----------+-------+
3)进行内连接:
mysql> select * from student,score where student.id=score.studentID;
+------+------+-----------+-------+
| id   | name | studentID | score |
+------+------+-----------+-------+
|    1 | A    |         1 |    90 |
|    2 | B    |         2 |    80 |
+------+------+-----------+-------+
2 rows in set (0.00 sec)

mysql> select * from student join score on student.id=score.studentID;
+------+------+-----------+-------+
| id   | name | studentID | score |
+------+------+-----------+-------+
|    1 | A    |         1 |    90 |
|    2 | B    |         2 |    80 |
+------+------+-----------+-------+
2 rows in set (0.00 sec)

我们此时就发现(3,C)这条记录,只在student表中存在,不会出现在score表中;但是(4,70)这条记录只在score表中存在,没有出现在student表中;

1)select * from student join score on studentID=id;此时我们发现,内连接里面的记录就是包含两张表里面同时拥有的记录;

2)select * from student left join score on id=studentID;
左外连接就是以左侧表为主
左侧表的每一条记录都在左外连接中有所体现
右侧表中不具有的属性就直接填成空
3)右外连接select * from student right join score on id=studentID;
此时我们就会发现
右外连接就是以右侧的表为主
右侧表中的每一条记录都在结果中有所体现
左侧表中不存在的数据就算成空;

group by进行分组的时候,指定列的值,相同的记录被分到了同一个组,分组还可以按照条件进行筛选分组之前指定条件要用where,分组之后指定条件要用having 

5)自连接:将自己和自己进行笛卡尔积,用来处理特殊场景;

1)自连接的本质,实际上是将行与行之间的转换关系,转化成列和列;在之前写的SQL语句,本质上是对列和列进行查找,例如 select score id name,chinese,math,english from student,如果我们查询chinese>english就会非常好找,因为这是按照列来进行比较

2)现在需要查询chinese的成绩大于english的同学

 select * from student;
+----+--------------+------+---------+----------+
| id | student_id   | name | qq_mail | class_id |
+----+--------------+------+---------+----------+
|  1 | 202110201001 | A    | 131.com |        1 |
|  2 | 202110201002 | B    | 132,com |        1 |
|  3 | 202110201003 | C    | 133.com |        1 |
|  4 | 202110201004 | D    | 135.com |        1 |
|  5 | 202110201005 | E    | 136.com |        1 |
|  6 | 202110201006 | F    | 137.com |        2 |
|  7 | 202110201007 | G    | 138.com |        2 |
|  8 | 202110201009 | H    | 139.com |        2 |
+----+--------------+------+---------+----------+

 select * from class;
+---------+---------+---------------+
| classID | name    | about         |
+---------+---------+---------------+
|       1 | Java100 | very nice     |
|       2 | java101 | very rubblish |
|       3 | java102 | nice          |
+---------+---------+---------------+

 select * from course;
+----------+---------+
| courseID | name    |
+----------+---------+
|        1 | chinese |
|        2 | math    |
|        3 | english |
+----------+---------+

 select * from score;
+-------+-----------+-----------+
| score | studentID | course_id |
+-------+-----------+-----------+
|    71 |         1 |         1 |
|    99 |         1 |         3 |
|    33 |         1 |         5 |
|    98 |         1 |         6 |
|    60 |         2 |         1 |
|    60 |         2 |         5 |
|    33 |         3 |         1 |
|    68 |         3 |         3 |
|    99 |         3 |         5 |
|    67 |         4 |         1 |
|    23 |         4 |         3 |
+-------+-----------+-----------+
上面就不得不按照行来进行比较了,看看studentID=1的列是否满足对应的语文成绩大于英语成绩

1)course_id=1对应的课程是chinese,course_id=3对应的课程是english,满足chinese<english,在肉眼的过程中,是按照行来进行比较的,就需要把行转化成列

就会产生大量的临时数据,两张表结合在一起之后,只有学生的id相同才是有效数据

select * from score as s1,score as s2 where s1.studentID=s2.studentID;

现在这里面还有一些其它课程的分数,是用不到的,所以我们需要在增加一些筛选条件:例如我们让s1里面的数据只保留id=3的记录,我们让s2的数据只保留id=1的记录;

保证左侧的成绩一定是语文成绩,右侧一定是英语成绩

select * from score as s1,score as s2 where s1.studentID=s2.studentID  and s1.course_id=3 and s2.course_id=1;

然后我们再根据where语句增加条件进行筛选 

select * from score as s1,score as s2 where s1.studentID=s2.studentID  and s1.course_id=3 and s2.course_id=1 and  s1.score>s2.score;

最终结果如下图:

所以自连接的关键是将行比较转换成列比较

6)子查询:本质上来说是把多个select合并成一个

将一张表的查询结果作为另一张表查询的搜索条件

1)单行子查询

一)查询一下very nice的同班同学,先去查找very nice 的班级ID,然后再根据班级ID在学生表中出查询出同classID的同学,这里面虽然分成两步,但是是针对一张表来进行查询的;

经过子查询之后,可以写成这样select name from student where class_id=(select class_id from student where name="A");(将两个SQL合并在一起)

二:查询一下chinese或者math相关的成绩信息

要先去查询chinese和math的课程ID,然后再去score里面根据course_id去查询成绩信息;

 也可以写成一条语句来展现出结果:两个SQL合并在了一起

7)合并查询:把多个查询语句的结果给合并到一起了

union:不会进行去重

union all:会自动进行去重 

核心就是通过union把两个sql的查询结果给合并到一起了,合并的前提是两个SQL查询到的列必须是对应的

1)查询course_id<3或者名字为chinese的课程,也可以用or来进行替换,但是使用or必须保证是针对同一张表的来指定的多个条件来进行查询

2)但是合并查询是可以针对不同的表

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/132827.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

如何将一个 HRESULT 转换为 Win32 错误码?

地球人都知道&#xff0c;可以使用 HRESULT_FROM_WIN32 这个宏将一个 Win32 错误码转换为一个 HRESULT&#xff0c;但是如何将一个 HRESULT 转换为 Win32 错误码呢&#xff1f; 让我们先看看 HRESULT_FROM_WIN32 这个宏的定义&#xff1a; #define HRESULT_FROM_WIN32(x) \ ((…

[LeetCode]-622. 设计循环队列

目录 662. 设计循环队列 题目 思路 代码 662. 设计循环队列 622. 设计循环队列 - 力扣&#xff08;LeetCode&#xff09;https://leetcode.cn/problems/design-circular-queue/ 题目 设计你的循环队列实现。 循环队列是一种线性数据结构&#xff0c;其操作表现基于 FIFO&…

硝烟后的茶歇 | 中睿天下谈攻防演练之邮件攻击溯源实战分享

近日&#xff0c;由中国信息协会信息安全专业委员会、深圳市CIO协会、PCSA安全能力者联盟主办的《硝烟后的茶歇广东站》主题故事会在深圳成功召开。活动已连续举办四年四期&#xff0c;共性智慧逐步形成《年度红蓝攻防系列全景图》、《三化六防“挂图作战”》等共性研究重要成果…

NSF服务器

1.简介 1.1 NFS背景介绍 NFS是一种古老的用于在UNIX/Linux主机之间进行文件共享的协议。它古老到你必须穿着白大补才能接近一台计算机的年代。在那个年代&#xff0c;所有的联网计算机都被认为是可信的&#xff0c;而不像现今这样&#xff0c;任何人都有多种多样方法能连接到你…

视频剪辑技巧:探索画中画视频剪辑,如何制作引人入胜的视觉效果

在视频制作领域&#xff0c;画中画视频剪辑是一种备受瞩目的技术&#xff0c;它可以将多个视频画面叠加在一起&#xff0c;形成一种独特的视觉效果。这种剪辑技巧可以让观众同时看到两个或多个视频片段&#xff0c;创造出一种引人入胜的视觉体验。在开始画中画视频剪辑之前&…

SQL必知会(二)-SQL查询篇(3)-过滤数据

第4课、过滤数据 WHERE&#xff1a;过滤条件 使用 WHERE 子句 指定搜索条件进行过滤。 WHERE 子句操作符 表4-1 WHERE 子句操作符 操作符说明操作符说明等于>大于< >不等于>大于等于!不等于!>不大于<小于BETWEEN在指定的两个值之间<小于等于IS NULL为…

线程活跃性

文章目录 1. 简介2. 死锁3. 活锁4. 饥饿 1. 简介 所谓线程的活跃性&#xff0c;我们知道每个线程所要执行的java代码是有限的&#xff0c;在执行一段时间后线程自然会陷入Terminated状态&#xff0c;但由于某些外部原因导致线程一直执行不完&#xff0c;一直处于活跃状态&…

leetCode 493 翻转对 归并分治 + 图解

493. 翻转对 - 力扣&#xff08;LeetCode&#xff09; 给定一个数组 nums &#xff0c;如果 i < j 且 nums[i] > 2*nums[j] 我们就将 (i, j) 称作一个重要翻转对。你需要返回给定数组中的重要翻转对的数量。 求"小和"问题是&#xff0c;当我 j 来到一个位置的…

快速排序实现方法(剑指offer思路)

快速排序思想 从参与排序的数组中&#xff0c;选择一个数&#xff0c;把小于这个数的放在左边&#xff0c;大于这个数的放在右边&#xff0c;然后递归操作。 实现算法思路 选择最后一个当作参考值&#xff0c;使用small索引当作比这个数小的下标值遍历数组&#xff0c;如果小…

【Python】 Python 使用 Pillow 处理图像:几何变换

Python 使用 Pillow 处理图像&#xff1a;几何变换 pillow库操作切片、旋转、滤镜、输出文字、调色板等功能一应俱全。 1. 几何变换 Image 包含调整图像大小 resize() 和旋转 rotate() 的方法。前者采用元组给出新的大小&#xff0c;后者采用逆时针方向的角度。 调整大小并…

n-gram语言模型——文本生成源码

n-gram语言模型——文本生成源码 n-gram模型的基本原理 文本生成的步骤 1. 准备和分词 2. 构建n-gram模型 3. 平滑技术的应用 4. 生成文本 源码 在自然语言处理的领域中&#xff0c;n-gram语言模型是一种基础而强大的工具。它通过考虑词汇的序列来预测文本内容&#xff…

MXNet中图解稀疏矩阵(Sparse Matrix)的压缩与还原

1、概述 对于稀疏矩阵的解释&#xff0c;就是当矩阵里面零元素远远多于非零元素&#xff0c;且非零元素没有规律&#xff0c;这样的矩阵就叫做稀疏矩阵&#xff0c;反过来就是稠密矩阵&#xff0c;其中非零元素的数量与所有元素的比值叫做稠密度&#xff0c;一般稠密度小于0.0…

Python开发运维:Python3.7使用QQ邮箱发送不同类型邮件

目录 一、理论 1.邮件发送 二、实验 1.Python3.7使用QQ邮箱发送普通邮件 2.Python3.7使用QQ邮箱发送包含图片与附件的邮件 三、问题 1.Pycharm中如何放大和缩小代码界面 一、理论 1.邮件发送 &#xff08;1&#xff09;概念 SMTP&#xff08;Simple Mail Transfer Pro…

Linux AMH 服务器管理面板远程访问

文章目录 1. 前言2. Linux 安装AMH 面板3. 本地访问AMH 面板4. Linux安装Cpolar5. 配置AMH面板公网地址6. 远程访问AMH面板7. 固定AMH面板公网地址8、结语 1. 前言 AMH 是一款基于 Linux 系统的服务器管理面板&#xff0c;它提供了一系列的功能&#xff0c;包括网站管理、FTP …

Linux-用户与用户组,权限

1.用户组管理&#xff08;以下命令需root用户执行&#xff09; ①创建用户组 groupadd 用户组名 ②删除用户组 groupdel 用户组名 2.用户管理&#xff08;以下命令需root用户执行&#xff09; ①创建用户 useradd [-g -d] 用户名 >-g&#xff1a;指定用户的组&#xff0c;不…

颠覆人工智能计算硬件的新计算技术

颠覆人工智能计算硬件的新计算技术 图纸解释说明参考网址加法器模拟解析图纸 解释说明 简单的介绍 使用一个小的llm 模拟 计算最小单元加法器 等硬件 在使用 简单的 电阻矩阵模拟矩阵计算 固化llm 参数代替 半导体硬件 而后组成 大规模人工智能计算 参考网址 加法器 但是直接…

TCP与UDP

文章目录 TCP与UDP传输层的作用端口号UDPTCPUDP首部的格式TCP首部格式 TCP与UDP TCP/IP中有两个具有代表性的传输层协议&#xff0c;它们分别是TCP和UDP。TCP提供可靠的通信传输&#xff0c;而UDP则常被用于让广播和细节控制交给应用的通信传输。总之&#xff0c;根据通信的具…

win10使用mingw安装OpenCV4.8

1. cmake安装 下载链接如下https://github.com/Kitware/CMake/releases/download/v3.27.7/cmake-3.27.7-windows-x86_64.zip 解压后放到指定目录后&#xff0c;添加bin目录到环境变量即可。 2. mingw安装 下载链接如下(下图的x86_64-posix-sjlj)&#xff1a; Download x86_…

mybatis的简单教程

整体就是mysql里存了一张表&#xff0c;然后在java程序里用mybatis把数据读出来的一个简单示例。 库 blog里有一张表 article 整个项目就是增加了这3个文件 首先是mybatis-config.xml文件 <?xml version"1.0" encoding"UTF-8" ?> <!DOCTYPE c…

【操作系统内核】线程

【操作系统内核】线程 为什么需要线程 比如我要做一个视频播放器&#xff0c;就需要实现三个功能&#xff1a; ① 从磁盘读取视频数据 ② 对读取到的视频数据进行解码 ③ 对解码的数据进行播放 如果串行执行&#xff08;通过一个进程来执行&#xff09;&#xff1a; 那么…