数据库--学习记录

1.MySQL引入

1.1软件目录开发规范

"""
------
流行蝴蝶剑
—-----

-conf:这个项目的配置文件
-core:核心逻辑;
-lib:公共的方法;
log:日志;
-bin:放置启动文件
-db:程序运行过程中产生的一些数据
readme.md:程序说明书
“”“

1.2 数据库引入

要将单机游戏,转变成为联网游戏,就是需要一个服务端存数所有客户端共有的数据部分,被称为数据库或是数据服务端。而这些向数据库发送请求的就被成为数据库客户端。也就是一个基于网络通信的应用程序,客户端发请求,服务端存储数据。客户端可以有多个,服务端只是有一个。所有客户端可以和服务端进行交互。

1.3 主流的数据库程序

1.3.1 关系型数据库

MySQL,Oracle,SQL server,DB2,Access

特点:

1)数据之间有关系或者约束(一张表的一条数据,和另一张表的多条数据有关系)

2)数据通常以表格的形式进行存储

1.3.2非关系型数据库

MongoDB,Redis,Memcache

存储数据通常都是key,value的形式。

2.MySQL引入

mysql是一款基于网络通信的应用程序,底层一定是用的socket.

mysql服务端它支持编程语言来作为它的客户端,就是用代码来操作mysql数据库。它支持masql自己客户端语言来操作数据,也支持其他编程语言来作为客户端操作数据。怎么解决语言不同的问题?

--让服务端精通所有编程语言(写客户端的时候,进行判断,判断和数据库连接的客户端使用的是什么语言,切换成为一样的语言进行交互。

--同一语言,这个语言的语法由写这个数据库软件的人来定制(SQL语句)

3.MySQL安装

https://www.mysql.com/进行官网,选择社区版,进行下载

数据库--学习记录_第1张图片

点击MySQL Community Server进行下载 

数据库--学习记录_第2张图片

下载版本求稳不求新,避免新版本的兼容性问题。公司使用的是5.6或是5.7 。点击第2个压缩包进行下载。

数据库--学习记录_第3张图片

 将双击解压之后的mysql,移动到/usr/local路径下面,sudo是使用超级用户进行执行该操作。

使用 open mysql打开此文件夹

数据库--学习记录_第4张图片 bin文件夹里面放置的都是可执行文件,

--mysql:它就是mysql客户端,我们要是连接客户端就是需要它

--mysqld:它就是mysql的服务端,不过我们启动服务端不是直接执行它

数据库--学习记录_第5张图片

 我们启动服务端使用的是support-files里面的mysql.server文件,启动的时候它会帮我们做一些配置,所以这些要执行的文件我们需要将其配置到环境变量里面。

数据库--学习记录_第6张图片

4.mac系统下配置MySQL

mac系统的环境变量和windows系统的不太一样,它是通过配置文件来进行添加的。环境配置文件为:/etc/profile,这是系统级别的配置文件。

4.1 配置系统级别环境变量

使用export进行配置:

$表示取值,表示取原来的PATH,因为系统会自带一些环境变量

在mac和linux里面环境变量的分割,使用的是:

$PATH:/var/bin:/usr/local/mysql/bin:/usr/local/mysql/support-files

数据库--学习记录_第7张图片

4.2 使配置文件立即生效 

修改配置文件之后不会立即生效,需要重启之后才会生效, 可以使用指令 source /etc/profile使得配置文件立即生效。现在再次输入mysql就不会再提示没有找到。而是显示ERROR,不能连接到本地mysql,这就表示我们环境变量配置成功了。

4.3 用户目录下的配置文件 

因为配置的是系统级别的环境变量,但是每次启动终端的时候,它加载的是用户级别的环境变量。所以还是需要执行一下 source /etc/profile.每次重启终端之后都要再次加载配置文件,很是麻烦。所以可以编辑用户目录下的配置文件.zshrc 里面只写一句话source /etc/profile,现在是真正配置好了环境变量。

 

4.4 初始化数据库 

环境变量配置好了之后,需要初始化数据库,还是需要超级用户来进行初始化。

由于配置了环境变量,可以在全局任意地方执行mysqld

--initialize表示初始化

--user=mysql:表示指定MySQL服务运行时,使用的用户身份,为了保证系统的安全,我们一般都会使用非特权用户,这个用户可以是任意用户,但是我们一般都会使用mysql

sudo mysqld --initialize --user=mysql

这里会给出一个初始密码,用户是root,地址是localhost,冒号之后的就是密码。 

数据库--学习记录_第8张图片

 数据库初始化好之后,安装目录里面就会多一个data文件夹,这就是存放数据的地方。如果将这个文件夹删除了,那么所有的数据都会没有了。

数据库--学习记录_第9张图片

4.5 启动mysql服务 

这里显示SUCCESS,就是表示服务端启动成功了。

sudo mysql.server start

数据库--学习记录_第10张图片

4.6 连接mysql服务端

mysql:客户端执行文件

-h localhost:我们要连接的服务端地址

-P 3306:服务端的端口号,

在本地使用的时候,这两个参数可以不写,因为这是默认值,只有远程连接的时候,才需要进行指定。 

-u:用户名

mysql -uroot -p

输入密码时,使用刚刚生成的密码,k5e,bM=5sm9a 粘贴进去。命令行这里显示mysql>就是表示我们已经连接上了

数据库--学习记录_第11张图片

4.7 重置密码

连接上之后的第一件事就是重置密码,不能使用其默认密码,因为我们记不住。而且不重置密码的话,它是不会让我们执行其他操作的。 这里的密码就是123。现在密码就重置好了

使用show databases;查看所有库,注意所有的sql语句都是以;结尾的 

ALTER USER 'root'@'localhost' IDENTIFIED BY '123';

数据库--学习记录_第12张图片

5.忘记密码怎么办

5.1 停止运行mysql服务端

现在可以看见控制台里面存在mysqld服务。

输入sudo mysql.server stop之后服务停止。

sudo mysql.server stop

数据库--学习记录_第13张图片

 5.2 以跳过授权验证的方式启动

sudo mysqld_safe --skip-grant-tables

这样启动之后登陆的时候就不用输入密码了。

 

再次开启一个终端输入:就可以跳过密码验证直接登陆

mysql -uroot -p

数据库--学习记录_第14张图片

5.3 修改MySQL数据库 

修改的就是mysql数据库里面的内容

数据库--学习记录_第15张图片

update mysql.user set authentication_string=password('123') where user='root' and host='localhost';

update mysql.user:修改mysql数据库里面的user表,用户相关的数据都在这里面

authentication_string:设置这张表里面的密码字段

password('123'):将用户传递的明文密码转为密文的形式

where user='root':判断是修改哪个用户的密码

host='localhost':判断这是是一个本地账号

 之前也重置过密码为什么两次的指令不一样?

因为第一次连接数据库,我们是使用不了其它sql语句的,所以第一次修改密码不可以使用这种方式

5.4 刷新授权

现在root用户的密码就被强行修改了,我们是跳过授权进去的

flush privileges;

数据库--学习记录_第16张图片

5.5 杀死mysqld服务端进程

使用sudo启动的服务端,也要用sudo进行杀死

 数据库--学习记录_第17张图片

5.6 启动服务端

sudo mysql.server start

5.7 连接服务端

mysql -uroot -p

数据库--学习记录_第18张图片

6.Windows系统下配置MySQL

6.1 下载压缩包

数据库--学习记录_第19张图片

6.2 将bin文件配置环境变量

下载解压之后翻入文件夹中,但是不能存在中文路径.之后就是配置环境变量,将bin文件的路径加入到系统的环境变量里面.

数据库--学习记录_第20张图片 6.3 初始化数据库

初始化数据库时,一定要用管理员身份运行cmd输入命令

mysqld --initialize-insecure --user=mysql会生成,data文件夹,所有的数据库的数据都会存储在这里面.

数据库--学习记录_第21张图片6.4 运行服务端

初始化好之后就可以运行服务端,mysqld.exe,.exe也可以不写,服务端启动成功之后,服务端会在后台进行运行.

数据库--学习记录_第22张图片

6.5 连接服务端 

在开启一个cmd连接服务端,输入mysql -uroot -p 即可连接数据库,并且还是没有密码.但是现在的问题是,我的数据库没有密码并且还是root账户没有密码,很是危险.

6.6 配置密码

输入mysqladmin -uroot -p password 123,[配置root账户密码为123

配置完成之后可以输入mysql -uroot -p123或者mysql -uroot -p再输入密码登录数据库

数据库--学习记录_第23张图片 7. windows服务

windows安装好MySQL之后,还是有一个问题,就是每次重启之后都是需要输入mysqld来重启服务比较麻烦.,如果重启之后不想在手动重启一次mysqld该如何做?可以将mysqld设置成为系统服务,系统服务就是说开机自启动.实现mysql服务端开机自启动.

7.1 安装和卸载 mysql服务

使用mysqld -install和mysqld -remove

 数据库--学习记录_第24张图片

7.2 启动mysql服务

输入net start mysql启动服务,这行代码是用来启动服务的,mysql是服务的名字.因为安装的时候内有给服务设置名字.服务默认的名字就是mysql,这里不要和客户端混淆了.会发现启动的服务会在任务管理器里面体现出来.

数据库--学习记录_第25张图片 如果发现端口被占用可以使用netstat -ano | findstr 3306查询占用端口的进程为6916

可以输入taskkill /F /PID 6916 杀死进程;/F为强制,/PID是进程号 

打开服务的时候发现服务的启动类型是自动,下次系统起来的时候,这个服务就会起来.以后开机的时候mysql就会自动启动.我们操作数据库的时候直接连接就行.

数据库--学习记录_第26张图片

数据库--学习记录_第27张图片

8.统一字符编码

8.1 mac电脑字符编码

对于mac系统而言,查询字符编码:进入mysql之后,输入\s,现在显示的还是存在两个latin1文。

数据库--学习记录_第28张图片

8.2 修改配置文件

对于mac上的mysql上面来说,要修改字符编码的话,同样是要修改配置文件,存放位置和centos一样。/etc/my.cnf

/etc 目录是一个系统级别的目录,所以需要使用超级用户打开。

sudo vim /etc/my.cnf

输入内容:

[mysqld]
character-set-server=utf8
collation-server=utf8_general_ci
[client]
default-character-set=utf8
[mysql]
default-character-set=utf8

8.3 重启服务端

输入 sudo mysql.server stop :停止服务

输入 sudo mysql.server start: 开始服务

 数据库--学习记录_第29张图片

8.4 查看修改之后的字符编码

再次输入mysql -uroot -p进入数据库

输入\s结果如下:全部变为utf-8编码

数据库--学习记录_第30张图片

8.5 window系统修改字符编码

 8.5.1 创建配置文件my.ini

windows下面的配置文件放置在根目录,创建配置文件my.ini

数据库--学习记录_第31张图片

配置文件内容如下:

[mysqld]
character-set-server=utf8
collation-server=utf8_general_ci
[client]
default-character-set=utf8
[mysql]
default-character-set=utf8

 8.5.2 重启服务

数据库--学习记录_第32张图片

8.5.3 查询修改之后的字符编码

数据库--学习记录_第33张图片

9.远程连接mysql

如何使用本机的mysql客户端,连接两外一台主机的mysql服务端

两台主机之间。。。。。

10.系统数据库

每一条sql都是以;结尾的,如果是不添加;则表示此条sql语句还是没有结束。

库:对应的就是文件夹

表:对应的就是文件夹里面的文件

记录:就是对应文件里面的一行行数据

那么这里的四张表就是对应四个文件夹

数据库--学习记录_第34张图片

显示安装目录下面的文件

sudo ls /usr/local/mysql/data/

可以看到只有三个文件,因为information_schema 是虚拟文件夹,它是存放在内存里面的。里面都是数据库启动之后的信息。比如数据类型和访问权限等

mysql:主要就是一个授权表,我们修改密码的时候就是修改里面的内容

performance_schema:提供一些数据监控和诊断功能,可以用来分析数据库的性能

sys:数据库引擎的扩展库

数据库--学习记录_第35张图片 11. mysql的字符含义及简化登陆

11.1 mysql语句的字符含义

单行注释:--

多行注释:/**/

\s:查看数据库字符编码以及其它信息

\c:结束当前语句

exit:退出连接

quit:退出连接

help:查看命令的帮助信息

11.2 简化登陆方式

我们现在涉及到经常性的退出和连接数据库,每次都要输入mysql -uroot -p,会有点麻烦。可以简化

编辑/etc/my.cnf文件,添加配置项目如下

数据库--学习记录_第36张图片

mysql自己的客户端连接的时候就会执行下面的配置,我们配置了之后就不需要再次输入 -uroot -p,密码也不再需要输入

当然修改配置文件之后,需要重启mysql服务

但是这个配置只是针对客户端有效,并且是本机的mysql客户端.

数据库--学习记录_第37张图片

12. 操作数据库

12.1 -- 增

db1是数据库名字,

create database db1;

create database db2 charset=gbk;

结果:在文件夹里面确实可以看到新增了文件夹db1,查询所有数据库,确实发现了db1

过程:

我们在客户端输入了一条命令,这个命令通过网络传输到了服务端,服务端在本地操作文件。所以说数据库就是一个远程操作文件的程序。我们操作本机的数据库也是一样的,只不过客户端和服务端都是在本地而已。

最好在创建数据库的时候加上字符编码,因为我们自己配置了编码格式utf8,即使不写,也会使用utf8编码,但是如果代码拿到别的电脑上面进行运行就是很有可能会出现问题。

数据库--学习记录_第38张图片

 

12.2 -- 删

drop(减少)

drop database db2;

数据库--学习记录_第39张图片

12.3 -- 改

对于数据库而言其实没有什么改的,能修改的只能是字符编码。alter(改变)

alter database db2 charset=utf8;

数据库--学习记录_第40张图片

12.4 -- 查

show databases; -- 查询所有数据库

show create database db1; -- 查一个,查看创建这个数据库的sql语句 

数据库--学习记录_第41张图片

12.5  数据库操作补充

-- 增

create database if not exists db1 charset=utf8;

-- 删

drop database if exists db1;

数据库已经存在,那么重复创建database就是会报错,现在添加判断条件就不会报错

数据库--学习记录_第42张图片

12.6 数据库操作语法汇总

--增

 create database [if not exists] <库名> [charset=utf8];

--删

drop database [ if exists] <库名>;

--改

alter database <库名> charset=utf8;

--查

show databases;

show create database <库名>;

12.7 MySQL帮助信息

如果输入的时候想不起某一个命令如何使用就可以使用help + 命令

数据库--学习记录_第43张图片

13. 操作数据表 

表是文件,文件一定是放在一个文件夹里面的,也就是说数据表一定是放在一个数据库下面的。所以我们在操作表的时候一定要指定所在的库。

select database(); -- 查询当前所在库的名字

use db1; -- 切换数据库

数据库--学习记录_第44张图片

现在数据库切换到db1之后,所有对于表的操作增删改查都是操作db1了

13.1 -- 增

新增表的时候,要设置表的结构,除了要设置表里面的字段,每一个字段都要指定它的类型

create table movies(id int,name char); -- 创建表(默认字符编码,就是库的字符编码)

create table movies(id int,name char)charset=utf8;--创建表

创建之后,db1数据库里面就多出来了两张表。为什么新建一张表,会多出两个文件?

这就是mysql存储数据的方式,它就是将一张表存储成为两个文件。frm存储的就是表的结构,也就是我们定义的字段,ibd储存的就是数据

数据库--学习记录_第45张图片

13.2 -- 删

drop table movies;  -- 删除movies 表

输出db1.movies不存在。我们操作表的时候,也可以这样做。如果我们当前所在数据库不是db1,但是又想操作db1,就可以使用这种写法。类似于python中的绝对路径

数据库--学习记录_第46张图片

13.3 -- 改

alter table movies modify name char(4); -- 修改字段类型,数字4就是字段的宽度

alter table movies change name Name char(4); -- 修改字段名和类型 

修改字段类型:

数据库--学习记录_第47张图片

修改字段名和类型 数据库--学习记录_第48张图片

13.4 -- 查

show tables; -- 查看当前库下面所有的表

show create table movies; -- 查看创建表的sql语句

describe movies; -- 查看一张表的结构,简写:desc movies;

输出结果:

这里的CREATE TABLE `movies`之所以添加反引号是为了防止和sql语句里面的关键字冲突,而且这里的大小写是没有关系的,sql对于大小写不敏感。

(

  `id` int(11) DEFAULT NULL,

  `name` char(1) DEFAULT NULL

)这里是设置的字段

CHARSET=utf8:设置表的字符编码,如果创建表的时候不指定这个编码,它会默认使用创建库的时候使用的编码。如果你创建库的时候也没有设置编码,它就会使用你配置文件里面的编码。配置文件也没有的话,直接使用默认的,就是latin的那个。

数据库--学习记录_第49张图片

表结构查询结果:

数据库--学习记录_第50张图片

13.5 绝对路径操作数据表

所有对于表的操作,如果我们没有切换到对应的数据库里面,都可以使用绝对路径的方式。这样即便不切换数据库也可以操作数据库对应的表

 数据库--学习记录_第51张图片

数据库--学习记录_第52张图片

14. 操作记录 

14.1 -- 增

insert into movies values(1,"流浪地球“);  -- 插入一条记录

insert into movies values(2,"流浪地球"),(3,"三体"); -- 插入多条记录

过程:切换库到db1->创建表movies->插入失败->修改表字段name的宽度->重新插入

插入时出现报错:

mysql> insert into movies values(1,"流浪地球");

ERROR 1406 (22001): Data too long for column 'name' at row 1

是因为我们创建表的时候,给name字段设置最多只能存储2个字符长度。但是”流浪地球"字段长度为4

插入单条记录:

数据库--学习记录_第53张图片

 插入多条记录:

插入的值为多个即可

数据库--学习记录_第54张图片

14.2 -- 删

删除的操作大概率只是会在学习的阶段或者调试阶段用到,在项目里面,即使是客户做出了删除的操作,但是在我们的记录里面不会是真的删除掉。而是会给这个数据打一个标记。表示这个数据已经被删除了,下次不要再展示了。

delete from movies; -- 清空这张表

delete from movies where name="三体“; -- 将三体这条记录删除掉

数据库--学习记录_第55张图片

14.3 -- 改

update movies set name="满江红" where id=1; -- 修改表movies里面的字段name改为满江红,只是针对id为1的记录

数据库--学习记录_第56张图片

14.4 -- 查

select * from movies; -- 查询这张表的所有字段,在数据量太大的时候不要使用

select id,name from movies; -- 查询这张表的素有id和name字段

select user,host from mysql.user; --  查询user表里面的所有user和host字段,在db1里面操作user表,必须使用绝对路径

select name from movies; -- 查询所有数据的单个name字段 

数据库--学习记录_第57张图片

15.SQL语句分类

类型 描述 关键字
DDL 数据库定义语言,用来定义和管理数据库或是数据表 create,alter,drop
DML 数据库操作语言,用来操作数据 insert,update,delete
DQL 数据库查询语言,用来查询数据 select
DCL 数据库控制语言,权限控制 grant,revoke,commit,rollback

16.表的详细操作

16.1存储引擎

在mysql里面创建数据库就是创建文件夹,创建数据表就是=创建文件。如果我们自己写一个数据库软件,来处理文件,那么针对不同类型的数据,应该使用不同类型的文件来处理。在数据库里面表就是文件,那么表肯定存在不同的类型。

数据库--学习记录_第58张图片

在mysql里面表的类型,就是存储引擎。对于不同的存储引擎,它提供了不同的处理机制。

show engines; -- 查看所有存储引擎

数据库--学习记录_第59张图片

16.2 通过存储引擎创建数据表

create tabel t1(id int,name char)engine=innodb; 

create table t2(id int,name char)engine=memory;

create table t3(id int,name char)engine=blackhole;

create table t4(id int,name char)engine=myisam;

数据库--学习记录_第60张图片

数据库里面的内容为:

1. t1是通过innodb创建的,它对应两个文件一个是表结构t1.frm,一个是表数据t1.ibd(innodb缩写)

2. t2是通过memory创建的,它的数据存在内存,不会存到硬盘,所以这里只有一个表结构t2.frm。并没有它的数据

3.它是通过blackhole创建的,它是不存储数据的,它也只有一个表结构t3.frm.

4.t4是通过myisam创建的,它对应三个文件,t4.frm还是表结构,t4.MYD(myisam data),t4.MYI(myisam index)是其索引文件,myisam支持全文索引。全文索引是一种用于快速搜索文本数据的索引技术,它可以对文本数据中的每个单词进行分词,并将这些单词与其所在的数据行建立索引关系。当用户使用关键词进行搜索的时候,系统可以快速的查询全文索引,找到包含关键词的文档或是数据行。通常用于搜素引擎。

数据库--学习记录_第61张图片

16.3 插入数据的效果

insert into t1 values(1,"a"); 

insert into t2 values(1,"a"); -- 存在内存,内存特点断电丢失,或者mysql服务端停止运行了。进程结束了,内存回收,数据也就是没有了

insert into t3 values(1,"a"); 

insert into t4 values(1,"a"); 

数据库--学习记录_第62张图片

重启mysql服务端,发现t2数据表里面的内容都已经丢失

 数据库--学习记录_第63张图片

 

16.4 创建表的语法

sql语句是可以换行的,;才是一条sql语句结束的标志。在同一张表里面,字段名是不可以重复的

注意:这个宽度不是字节,而是字符个数,或者是字符串长度,是我们在python里面使用len()查询的字符长度

create table <表名> (

        <字段名1> <字段类型>[(宽度)] [约束条件],

        <字段名2> <字段类型>[(宽度)] [约束条件],,

         <字段名3> <字段类型>[(宽度)] [约束条件1 约束条件2]

);

-- 宽度指的是字符个数,或者说是字符长度

-- 约束条件,注意顺序

[unsigned] |[zerofill]| [not null ]

--unsigned :无符号

--zerofill:0填充

--not null : 非空 

16.5 修改表的语法

16.5.1 --修改存储引擎

alter table <表名> engine=<存储引擎名字>;

数据库--学习记录_第64张图片

16.5.2 -- 修改表名

alter table <表名> rename <新表名>;

数据库--学习记录_第65张图片

16.5.3 --增加字段

alter table <表名> add <字段名> <字段类型> [(宽度)] [约束条件] [first | after <字段名>]; 

尾部增加字段:

数据库--学习记录_第66张图片

指定位置增加字段:通过after和first进行实现

 数据库--学习记录_第67张图片

16.5.4 -- 删除字段

alter table <表名> drop <字段名>;

数据库--学习记录_第68张图片

16.5.5 -- 修改字段

alter table <表名> modify <字段名> <新字段类型>[(宽度)] [约束条件];

alter table <表名> change <旧字段名> <新字段名> <新字段类型>[(宽度)] [约束条件];

所以约束条件到底是什么呢?

这里的Null就是空,类似于python里面的None。id 和 name两个字段都是YES,就是表明这两个字段都是可以为空的,都是可以插入空。name的字段限制了宽度为1,为什么这里可以插入null?这里的null它不是一个字符串,而是一个关键字。null这项为yes,这其实就是一个约束条件。

改字段类型或是约束条件的时候,如果表里面已经有数据了,而且有不符合你想改的约束条件。这个时候如果你想改类型或是约束条件的话,就是改不了的。比如说t1表里面已经有了一个null,再想将约束条件改为非null数据就是修改不了的。

数据库--学习记录_第69张图片

 使用约束条件,创建table:

数据库--学习记录_第70张图片

约束条件应用场景:

 数据库--学习记录_第71张图片

16.6 删除和复制表语法

16.6.1 -- 删除表

drop table <表名>;

16.6.2 -- 复制表

create table <新表名> select * from <旧表名>[条件];

16.6.3 -- 复制表结构

create table <新表名> like <旧表名>;

复制表结构和表记录:

 

 只是复制表结构:

id=1就是一个表达式,它就是一个条件,它的结果就是一个布尔值,所以是一个布尔值,他就可以随便写。查不出数据,它就是空,就可以直接复制表结构.

除此之外,还是有更加简单的方式,创建的表像是,就可以直接复制表结构.

数据库--学习记录_第72张图片

 create table t1 select * from movies where id=100;通过筛选出来的值为空创建表结构. 

数据库--学习记录_第73张图片

 create table t2 like movies;直接复制表结构

 数据库--学习记录_第74张图片

17.数据类型 

17.1 数值-int

17.1.1整型范围

一个Byte有8个bit,对于tinyint而言,就是一位用来表示符号,剩余7位表示大小.无符号就是8位都是用来表示大小;

以tinyint举例,默认指定tinyint类型时,使用的范围是有符号的.并且如果插入的记录超出了范围,直接会提示报错.

数据库--学习记录_第75张图片

类型 大小 范围(有符号) 范围(无符号) 描述
tinyint 1 Byte (-128,127) (0,255) 很小的整数
smallint 2 Byte (-32768,32767) (0,65535) 较小的整数
mediumint 3 Byte (-8388608,8288607) (0,16777215) 一般的整数
int 4 Byte (-2147483648,2147483647) (0,4294967295) 标准的整数
bigint 8 Byte (-9223372036854775808,9223372036854775807) (0,1844744073709551615) 较大的整数

17.1.2 无符号约束

默认添加tinyint数据类型为有符号

alter table t1 add m tinyint unsigned; --无符号添加字段

添加字段m之后之前加入的n数据内容,在字段m上都为Null.如果设置约束条件不可以为null,那么字段是数字就用0填充,字段是字符串就用空字符串填充.如果not null约束条件和unsigned一起用的话,unsigned一定要放在前面.

数据库--学习记录_第76张图片

 数字0填充和空字符串填充

数据库--学习记录_第77张图片

not null 不能在unsigned前面

 17.1.3 整型宽度

整型的存储宽度是固定死的,只有表里面的5种.在指定整型数据类型的时候给定宽度,那只是修改了显示宽度.

数据库--学习记录_第78张图片

17.1.4 显示宽度

指定的显示宽度,如果显示宽度不足会用0填充,但是没有设置填充效果的话看不出来.如果插入的记录超过了显示宽度,那么该多长还是显示多长.显示宽度根本影响不了它.所以说整型的显示宽度一点用也没有. 

int类型无符号的最大显示宽度是10,有符号的是11.其实就是int类型显示的最大数.它的长度就是10.默认显示的宽度就是很合理的,所以根本不需要我们去设置它的显示宽度.

除了整型类型之外,所有的宽度指的都是存储宽度.

数据库--学习记录_第79张图片

zerofill填充后的效果:

数据库--学习记录_第80张图片

int类型默认显示宽度

数据库--学习记录_第81张图片

17.2 数值-float 

E+38就是小数点往后移动38位,E-38就是小数点往前移动38位。

十进制小数转二进制就是:乘2取整法

3.625

3 -> 11

0.625 -> 0.625x2 = 1.25 0.25x2 = 0.5 0.5x2=1->0.101

3.625 -> 11.101

在大多数编程语言里面浮点数分为两种,单精度浮点数和双精度浮点数

浮点数表现形式:符号,尾数,基数,指数

+/-m*2^{^{^{^{^{}}}}}^e,由于基数2是固定的,所以只是需要2进制数表示出来符号尾数和指数就可以将浮点数进行存储了。

单精度浮点数(32位):符号(1位)+指数(8位)+尾数(23位)

双精度浮点数(64位):符号(1位)+指数(11位)+尾数(52位)

符号:用第一位数字表示正负,1->负,0->正或是0

尾数: 把小数点前的二进制数,固定为1的规则

类型 大小 范围(有符号) 范围(无符号) 描述
float 4 Bytes

(-3.402823466 E+38,-1.175494351 E38),0

(1.175494351 E-38,3.402823466351E+38)

0,(1.175494351 E-38,3.402823466E+38) 单精度浮点值
double 8 Bytes

(-1.797693134862315E+308,-2.225

0738585072014 E-308),0,(2.225073858507201E-308,1.797693

1348623157E+308)

0,(2.225073858507

2014E-308,1.797693134862

315E+308)

双精度浮点值
decimal decima(m,d) 依赖于m和d的值 依赖于m和d的值 小数值

17.3 字符 

17.3.1 字符类型分类

字符类型分类很多,只要了解两种

- char (定长字符串)

char(10)最多存储10个字符,如果超过10个字符,会直接报错,如果不足10个字符,空格补齐。

缺点:浪费空间,不论是几个字符,都会存储成为10个字符

优点:存取速度快

- varchar(变长字符串)

varchar(10)最多存储10个字符,如果超过10个字符,会直接报错,如果不足10个字符,直接存储。

优点:节省空间

缺点:存取速度慢,但是慢是相对于计算机而言的,因为节省空间,所以一般都是使用varchar 

17.3.2 空格填充

char_length():是mysql的内置函数,可将返回传递过去字符的长度

插入两组数据之后,发现长度都是一样的,这是因为char的name数据在硬盘上面存储的确实是带有空格的,但是经过查询之后,它会自动去除多余的空格,所以在使用的时候是感受不到有空格存在的.插入数据的时候补空格是补充在数据后面的,如果数据本身后面是带有空格的,那么在去掉空格的时候,会将数据本身的空格也认为是它补充的空格一起去掉.所以数据尾部如果是有空格的话,最好是使用varchar. 

数据库--学习记录_第82张图片

这里t5第二个数据长度为3的原因是将后面的两个空格全部去除掉了. 

数据库--学习记录_第83张图片

17.3.3 char和varchar的范围

宽度就是字符个数,char类型最多可以存储255个字符

对于varchar而言最多存储65535个字节,,但是我们在实际使用的时候要减少3个字节,因为它需要一个字节来标识是否可以为null,而且varchar的每一个数据都要有个头,用来记录长度标识.当数据长度小于255的时候,头部占据一个字节.255<数据<65535时,头部占据2个字节.所以我们可以使用的只有65532个字节.但我们在指定宽度的时候,指定的是字符个数.这个字符的个数受到字符编码的影响.gbk一个字符占据2个字节,它的范围就是65532/2=32766字符,如果是utf8,一个字符占据3个字节

65532/3=21844字符.

数据库--学习记录_第84张图片

17.3.4 字符宽度计算

varchar(变长字符串)

最大字符数=(65535-行其他字段总字节数量-null标志字节-长度标志字节)/字符集单个字符最大字节数.

虽然我们的varchar最大是21844,但是前提是这一行只有它一个字段.如果有其他字段,他们是共享这个65535字段的 .现在新增了一个id字段是int类型,int类型是4字节,char是utf8编码的所以是3字节.所以最少是要减少掉两个字符才能将其存储进去.

同时varchar的长度并不是越长越好,我们在定义长度的时候,最好只分配我们需要的空间.如果数据长度不超过255的话,我们定义的长度就不要超过255,超过255头部就会占据2个字节.

 17.4 时间日期

时间日期就没有宽度的概念,它的格式都是固定的.

year,年

date,年-月-日

time,时:分:秒

datetime 年-月-日 时:分:秒

8字节,1000~9999

timestamp

4字节,1970~2038

数据库--学习记录_第85张图片

使用mysql的内置函数now(),会自动获取系统时间,有因为存储的数据类型不同,会根据数据类型进行存储. 插入指定的时间,只需要将日期处理成为字符串即可

数据库--学习记录_第86张图片数据库--学习记录_第87张图片

17.5 枚举

enum:enumerate的缩写,单选,从给定的范围内选择一个值,插入其他值报错

数据库--学习记录_第88张图片

17.6 集合

set:表示多选,可以从给定范围内选择一个或是多个,不再范围内的则是会报错.

数据库--学习记录_第89张图片

18.约束条件

18.1 约束条件,注意顺序

[unsigned] |[zerofill] 放置在前面

[unsigned] |[zerofill]| [not null ] [ default ]

--unsigned :无符号

--zerofill:0填充

--not null : 非空 

--default:默认值

--unique key:唯一

其实严格来说unsigned和zerofill都是属于字段类型的,int是强制约束这个字段必须是整型,unsigned进行进一步约束,它是无符号的,接着进行0填充.而not null约束,它是对于字段的约束.所以我们在写约束条件的时候,约束条件要写在前面,字段约束要写在后面.

数据库--学习记录_第90张图片

 18.2 字段约束

Null:默认为yes,是可以为空的.只不过这里指定了not Null,指定非空的时候,要给出一个默认值就是Default(默认为NULL),可以通过default 设置默认值

create table t2(id int,name varchar(10),gender enum("male","female") not null default "male");

插入数据的时候可以通过指定字段,不插入默认值来实现数据的插入

insert into t2(id,name) values(1,"zz");

数据库--学习记录_第91张图片

18.3 单列唯一

我们往表里面存储的数据默认是可以重复的.如果想让字段唯一,不重复.就需要另外一个约束条件.unique key:唯一 场景(用户名唯一)

--单列唯一unique
--指定id和name唯一
create table users(id int unique,name varchar(10) unique);
create table users(id int,name varchar(10),unique(id),unique(name));

数据库--学习记录_第92张图片

18.4 联合唯一

单个是可以重复的,联合在一起却是唯一的.比如ip+端口,ip是可以重复的,端口是可以重复的但是ip+端口必须是唯一的.

--unique(host,port),就可以实现联合唯一
--联合唯一,两组一样的值是插入不进去的
create table route(id int,host varchar(15),port int,unique(host,port),unique(id));

数据库--学习记录_第93张图片

数据库--学习记录_第94张图片

18.5 单列主键

primary key:主键(不为空,且唯一),对于innodb这个存储引擎来说,每一张表都必须要有一个主键..主键还可以帮助我们组织数据,提高查询速度.注意:一张表必须有一个主键.为什么前面建表的时候,没有指定主键也没有出现问题?

如果我们没有指定主键,mysql会查询我们的字段,看看有没有不为空且唯一的字段.如果有的话,就将其作为主键.如果没有找到,mysql就会自动帮我们创建一个隐藏的主键,但是隐藏的主键,对于我们而言并没有实际的作用,他只是为了方便组织表的数据.而且我们是要用主键来加速查询的.

所以在建表的时候我们一定要自己指定一个主键

--主键是唯一且非空的
--主键实现方式是建表加入primary key
create table t1(id int primary key,name varchar(10));

数据库--学习记录_第95张图片

18.6 复合主键

之前说过int 类型设置为非空,默认会使用0进行填充.但是这是在新增字段的条件下,而不是说插入数据的时候,不设置数据会被default 0进行填充.

数据库--学习记录_第96张图片

如果我们在创建表的时候没有设置主键,就会将非空且唯一的数据作为主键.所以主键的

约束特性: 就是非空且唯一.所以现在创建每一张表,我们都应该给它一个id字段,并且将id字段作为主键.现在我们使用的主键也可以叫做单列主键

复合主键:就是前面的两个字段联合起来,作为一个主键

--复合主键
--复合主键的实现方式类似于联合唯一,使用primary key(host,port)
create table t3(id int,host varchar(15),port int,primary key(host,port),unique(id));

数据库--学习记录_第97张图片

18.7 auto_increment:自动递增

之前说过每一张表都应该有一个id字段,我们一般都是将id设置成为主键,用来标示每一条记录.但是我们每次插入数据的时候都需要加上id,但是id并不属于数据.所以可不可以不插入id,让其自动生成呢?

创建表的时候,给主键id指定,自动递增

--自动递增
--设置primary key时设置 auto_increment
create table t1(id int primary key auto_increment,name varchar(16));
--插入数据时候要注意指定字段名,否则会报错
insert into t1(name) values("hh"),("rose"),("jack");
--但是设置自动递增之后也是可以指定id进行插入的,并且递增是在上一条记录上面增加的
insert into t1 values(10,"ss");

数据库--学习记录_第98张图片

递增是在上一条记录上面增加的 

数据库--学习记录_第99张图片

18.8 清空表

trancate:截断,舍弃.

-- 清空数据,不清空自增值
delete from t1;
--同时清空数据和自增值
trancate t1;

清空表可以通过以上两种方式实现,如何查看自己的自增值是否发生改变呢?

--查看表的创建,里面存在自增值,即插入下一个数据的id号
show create table t1;

自增值为14,插入下一个数据id为14. 

数据库--学习记录_第100张图片

tranctae t1;之后数据表的记录和自增值都被清空,从1开始.再次插入数据,数据的id号码为1.

数据库--学习记录_第101张图片

19.外键

19.1 外键引入

之前就是说过mysql是关系型数据库,现在开始表与表之间建立关系.也算是另外一种约束条件.

foreign key:外键约束 

emp
id name gender mobile dep_name dep_desc
1 张三 male 123 研发部 造火箭
2 李四 female 456 销售部 卖火箭
3 王五 male 789 销售部 卖火箭
4 赵六 male 012 人事部 裁员的
5 秦七 female 345 人事部 裁员的

这样存储的信息存在大量的重复信息,并且以后数据修改也会很麻烦.使用解耦合的思想,将部门表拆分出来即可.并且使用dep的主键,就和emp表之间建立了关联

19.2 内容

19.2.1 表的定义

我们使用dep_id使得两张表之间建立了关联,那么dep_id是不是一定要来源于dep表呢?原则上是这样的,但是我们也可以不遵循.但是这样肯定是不合理的.所以对于dep_id应该要有一定的约束,它必须来自于部门表里面存在的id,如果存储了部门表里面不存在的id,它就会直接报错.要实现这个效果,就需要用到外键.

emp
id name gender mobile dep_id
1 张三 male 123 1
2 李四 female 456 2
3 王五 male 789 2
4 赵六 male 012 3
5 秦七 female 345 4

19.2.2 表的创建 

--创建部门表
--针对字段desc是关键字,需要使用反引号
create table dep(
    id int primary key,
    name varchar(16),
    `desc` varchar(64)
);
--创建人员表
--创建外键约束关联dep表的id字段
--现在的创建的表要关联部门表,但是部门表根本不存在,所以需要先创建部门表
create table emp(
    id int primary key,
    name varchar(16),
    gender enum("male","female"),
    dep_id int,
    foreign key(dep_id) references dep(id)
);

数据库--学习记录_第102张图片 插入人员表数据时,一定要保证部门表里面是存在数据的,否则关联的部门表里面的数据若是不是存在的话,会直接报错.

19.2.3 表内容的插入

--先插入部门表的信息
insert into dep values(1,"研发部","造火箭的"),(2,"销售部","卖火箭的"),(3,"人事部","裁员的");
--再插入人员的信息
insert into emp values(1,"张三","male",123,1),(2,"李四","female","456",2),(3,"王五","male",789,2),(4,"赵六","male",012,3),(5,"秦七","male",345,3);

数据库--学习记录_第103张图片

数据库--学习记录_第104张图片

19.2.4 表内容的删除 

直接删除部门表里面的信息会提示"外键约束错误"报错,因为部门的id在emp表里面有引用.就类似我们电脑里面的文件处于打开的文件,我们删除的话,电脑就会提示文件被占用.所以删除dep表里面的内容,得先将emp表里面引用的人全部删除才能过引用. 

数据库--学习记录_第105张图片

19.3 同步

现在删除部门表的信息还要先删除所有人员的信息.有没有方法删除部门表的信息之后,自动让所有人员表里面的信息自动删除.

我们现在是可以更新部门表里面的字段,但是同样原因id被引用,所以无法被修改.

--更新dep表里面的部门
update dep set name="市场部" where id=2;
--更新id,失败
update dep set id=100 where id=3;

数据库--学习记录_第106张图片

 解决的方式就是在创建表的时候,设置外键删除同步,更新同步

--删除emp人员表
drop table emp;

--重新创建表,并且设置外键删除同步,更新同步
create table emp(
    id int,
    name varchar(16),
    gender enum("male","female"),
    mobile int,
    dep_id int,
    foreign key(dep_id) references dep(id)
    on delete cascade
    on update cascade
);

--重新插入被删除的研发部信息
--指定id之后,会自动排序
insert into dep values(1,"研发部","造火箭的");

--重新插入人员信息
insert into emp values(1,"张三","male",123,1),(2,"李四","female","456",2),(3,"王五","male",789,2),(4,"赵六","male",012,3),(5,"秦七","male",345,3);

--现在删除emp表的内容,人员表也会自动删除,更新也是一样的
delete from dep where id=2;
update dep set id=999 where id=1;

创建表emp,并设置删除和更新同步 

数据库--学习记录_第107张图片

删除部门id=2 

 数据库--学习记录_第108张图片

修改部门id为999

 数据库--学习记录_第109张图片

19.4 不使用外键

我们好不容易将两张表解耦合之后,现在又使用foreign key本质将两张表耦合在一起了.虽然删除同步,更新同步,但是两张表始终都是强关联的.所以以后写大型项目的时候,一定不要使用外键.一切外键概念必须在应用层解决.这里使用foreign key建立的外键,可以理解为物理层的强关联,用起来很不灵活. 但是对于小型项目而言,外键结合django的orm就很香了,外键随便使用.

20. 关系

之前说过foreign key是用来给表与表建立关系的 .这个关系其实还是有几种分类

20.1 多对一

左边表的多条数据对应右边表的一条数据,设计表的时候要站在两边进行观察.一边是多对一的关系,另外一边一定不是多对一的关系.外键就要建立在多的那一边类似于前面的dep表和emp表之间的关系.

20.2 多对多

song
id name
1 以父之名
2 夜的第七章
3 止战之殇
4 夜曲
5 北京欢迎你
singer
id name
1 周杰伦
2 刘欢
3 韩红
4 成龙
song2singer
id signer_id song_id
1 1 1
2 1 2
3 1 3
4 1 4
5 2 5
6 3 5
7 4 5
--创建song表

create table song(
id int primary key,
name varchar(16)
);

--创建singer表
create table singer(
id int primary key,
name varchar(16)
);

--创建song2singer表
create table song2singer(
id int primary key,
signer_id int,
song_id int,
foreign key(signer_id) references singer(id)
on delete cascade
on update cascade,
foreign key(song_id) references song(id)
on delete cascade
on update cascade
);

--song表插入数据
insert into song values(1,"以父之名"),(2,"夜的第七章"),(3,"止战之殇"),(4,"夜曲"),(5,"北京欢迎你");

--singer表插入数据
insert into singer values(1,"周杰伦"),(2,"刘欢"),(3,"韩红"),(4,"成龙");

--song2singer表插入数据
insert into song2singer values(1,1,1),(2,1,2),(3,1,3),(4,1,4),(5,2,5),(6,3,5),(7,4,5);

为什么多对多的删除了singer只是song2singer的表同步删除,但是song表里面没有变化?

数据库--学习记录_第110张图片

 20. 3 一对一

存在客户表和业主表,潜在的客户表最终发展成为业主.多个客户不能发展成为同一个业主,多个业主也不可能是由同一个客户发展而来的.一个客户只能发展成为一个业主.一个业主只能由一个客户发展而来,这就是一对一的关系.现在要建立关系,不管是什么表,只要是建立关系,就是foreign key.理论上外键建立在哪里都是可以的,但是如果外键建立在customer表里面,要插入数据必须owner表里面先存在数据.所以结合实际,外键应该建立在owner表里面.

foreign key只能保证owner表的信息来自于customer,但是不能保证数据是唯一的,加上unique约束.

customer
id name gender mobile
1 张三 male 123
2 李四 female 456
3 王五 male 789
4 赵六 male 012
5 秦七 female 345
--创建customer表
create table customer(
id int primary key auto_increment,
name varchar(16) not null,
gender enum("male","female"),
mobile int not null
);
--创建owner表
create table owner(
id int primary key auto_increment,
room_num int not null,
area int not null,
is_loan enum("TRUE","FALSE"),
customer_id int unique,
foreign key(customer_id) references customer(id)
on delete cascade
on update cascade
);
--插入custoer数据
insert into customer(name,gender,mobile) values("张三","male",123),("李四","female",456),("王五","male",789),("赵六","male",012),("秦七","female",345);
--插入owner数据
insert into owner(room_num,area,is_loan,customer_id) values(688,300,"FALSE",2),(233,180,"TRUE",4);

数据库--学习记录_第111张图片

21. 记录的查询语法

21.1 单表查询语法

select  distinc <字段....> from <库名>.<表名>

        where <过滤条件>

        group by <分组条件>

        having <过滤条件>

        order by <排序字段> {ASC | DESC} --默认升序ASC

        limit n;

--创建员工表

create table emp(
    id int primary key auto_increment,
    name varchar(16) not null,
    gender enum("male","female") not null,
    age int not null,
    salary float(10,2),
    dep varchar(32),
    notes varchar(64)
);


-- 插入内容

insert into emp(name,gender,age,salary,dep) values
("关羽","male",20,8000,"技术部"),
("张飞","male",18,7000,"技术部"),
("刘备","male",28,9000,"技术部"),
("赵云","male",15,10000,"技术部"),
("曹操","male",28,12000,"研发部"),
("荀彧","male",21,9000,"研发部"),
("许攸","male",20,8000,"研发部"),
("夏侯惇","male",20,7000,"研发部"),
("孙权","male",10,6000,"人事部"),
("周瑜","male",20,10000,"人事部"),
("小乔","female",20,8000,"人事部"),
("大乔","female",22,8500,"人事部");

21.2 去重

通过关键字distinct实现去重,在筛选的字段前面加上即可.但是需要注意的是,这个去重是去除筛选记录的重复,如果筛选出来的内容一整条里面,只有部分是重复的,就无法去重.

--去重
select distinct emp from emp;

数据库--学习记录_第112张图片

数据库--学习记录_第113张图片

21.3 四则运算

我们查询出来的记录可以做加减乘除运算 

--四则运算
--计算出年薪并且修改名字
select name,salary*12 as yearly_salary from emp;

数据库--学习记录_第114张图片

21. 4 格式化显示

将查询的数据设置成为需要的格式,使用concat()函数和concat_ws()函数

-- 设置显示格式
-- 姓名: 关羽 年龄:20 薪资:8000
-- 直接使用concat进行拼接
select concat("姓名:",name,"    年龄:",age,"    薪资:",salary) from emp;
-- 重命名
select concat("姓名:",name,"    年龄:",age,"    薪资:",salary) as "姓名 年龄 薪资" from emp;
-- 直接使用concat_ws()进行拼接,第一个参数是拼接符号
select concat_ws("-",name,age,salary) as "姓名-年龄-薪资" from emp;

concat查询:

数据库--学习记录_第115张图片

concat查询并重命名:

数据库--学习记录_第116张图片

 concat_ws()查询:

数据库--学习记录_第117张图片

21.5 where 

我们的查询语句是有优先级的 from table -> where 条件 ->select 执行查询

where的条件查询支持not and or

where条件查询也支持in 范围查询,is null 空数据查询, like 模糊查询

-- where单条件查询
select name, age from emp where age> 25;
-- where多条件查询
select name, age, dep from emp where age>=20 and dep="技术部";
-- where 区间查询支持between(20<=X<=25)
select name, age from emp where age between 20 and 25;
-- where or条件查询
select name, age from emp where age<20 or age>25;
-- where not条件查询
select name, age from emp where age not between 20 and 25;

数据库--学习记录_第118张图片数据库--学习记录_第119张图片

-- 找到工资为7000 8000 9000的员工
select name, salary from emp where salary=7000 or salary=8000 or salary=9000;

-- 使用in范围值查询
select name, salary from emp where salary in (7000,8000,9000);

-- is null判断数据是否为空,注意空字符串不是null
select name, notes from emp where notes is null;

-- is null 取反
select name, notes from emp where notes is not null;

-- like(模糊匹配)
-- like里面的_类似于正则表达式里面的.
-- like里面的%类似与正则表达式里面的.*
select name from emp where name like "荀_";

 in 范围查询:

数据库--学习记录_第120张图片

is null 空数据查询:

 数据库--学习记录_第121张图片

模糊查询:

 数据库--学习记录_第122张图片

21.6 group by (分组条件)

group by是在where之后执行,书写sql语句的时候,也要遵循这个顺序

from table -> where 条件查询 -> group by进行分组 -> select 执行查询语句 

分组的目的是分组之后统计每一组的数据,我们分组之后要操作的就是组了.对某一组数据进行统计的话,就需要使用聚合函数了

21.7 聚合函数

作用就是从某一组中聚合出我们需要的结果,聚合函数如下

count,我们可以使用任意字段进行统计但是前提是统计的字段里面不能有null.

max.min,sum,avg

如果我们对查出来的数据不做分组操作,它默认就是一组,查出来的所有数据就是作为一组.聚合函数针对的是组.所以我们不使用group by也是可以使用聚合函数的.

-- 统计每个部门员工的数量

select dep, count(dep) as dep_count from emp group by dep;

-- 统计每个部门年龄最大的员工
select dep, max(age) as max_age from emp group by dep;

-- 统计每个部门工资最低的员工
select dep, min(salary) as min_salary  from emp group by dep;

-- 统计每个部门总工资
select dep, sum(salary) as sum_salary  from emp group by dep;

-- 统计每个部门平均工资
select dep, avg(salary) as avg_salary from emp group by dep;

-- 统计所有员工的平均工资
select avg(salary) from emp;

数据库--学习记录_第123张图片

 数据库--学习记录_第124张图片

 数据库--学习记录_第125张图片​​​​​​​

21.8 group_concat()

对分组内容进行拼接

-- 查询每个部门所有员工的名字
select dep, group_concat(name) from emp group by dep;

-- 统计每个部门年龄大于20的员工数量
select dep, count(name) as dep_count from emp where age>20 group by dep;

-- 统计男员工和女员工的数量
select gender, count(id) as gender_count from emp group by gender;

数据库--学习记录_第126张图片

21.9 having 过滤

having过滤是和where干的一样的事情,只不过它的执行顺序是在分组之后的,where是在分组之前进行过滤的

注意:分组之后的结果在被执行时一定要使用聚合函数,不然会报错

-- 查询所有部门内,员工数量小于4的部门名,以及该部门内的员工名和员工数量

select dep, group_concat(name) as name, count(id) as emp_count from emp group by dep having count(id)<=4;

-- 查询各部门年龄大于20的员工超过2个人的部门名,以及大于20的人数
-- 此种方式会报错,因为分组之后没有age字段了
select dep, count(id) from emp group by dep having age>20 and count(id)>2;

select dep, count(id) from emp where age>=20 group by dep having count(id)>2;

数据库--学习记录_第127张图片 数据库--学习记录_第128张图片

21.10 order by 过滤

排序只有两种,降序和升序.默认就是会按照id升序​​​​​​​ ,升序就是asc,降序就是desc.排序时可以指定第二个字段.对于工资相同的内容可以使用第二个字段进行排序.

-- 对于所有员工,按照员工工资进行排序
select * from emp order by salary;
-- 对于所有员工,按照员工工资进行排序-降序
select * from emp order by salary desc;
-- 对于所有员工,按照员工工资进行排序-工资相同按照年龄的升序
select * from emp order by salary,age;

数据库--学习记录_第129张图片

数据库--学习记录_第130张图片 21.11 limit

它的作用就是用来限制展示记录的条数

也可以实现分页功能,每一页只是显示几条到十几条记录,当用户点击下一页的时候,再显示下一页的数据.虽然直接使用limit可以实现分页,但是实际项目中并不是那么简单.实际项目中会用到一些缓存机制.

-- 查询所有员工信息只显示前5条
select * from emp limit 5;

-- 找出公司里面工资最高的5个人
select * from emp order by salary desc limit 5;

-- 实现分页功能
-- 从0开始往后取10条数据
select * from emp limit 0,10;
select * from emp limit 10,10;

数据库--学习记录_第131张图片

 数据库--学习记录_第132张图片

 21.12 正则表达式

模糊查询只有两个符号,实现更加复杂的查询就实现不了,现在支持mysql正则表达式

-- 正则表达式
select name from emp where name like "荀_";
select name from emp where name regexp "^荀.*";

-- 查询曹或是荀开头的名字
select name from emp where name regexp "^(荀|曹).*";

数据库--学习记录_第133张图片

你可能感兴趣的:(数据库,服务器,运维)