最新消息: USBMI致力于为网友们分享Windows、安卓、IOS等主流手机系统相关的资讯以及评测、同时提供相关教程、应用、软件下载等服务。

MySQL笔记(coderwhy老师Nodejs课程)

IT圈 admin 33浏览 0评论

2023年12月8日发(作者:戏冰)

MySQL笔记(coderwhy老师Nodejs课程)

MySQL 笔记

数据库概述

数据库通俗来讲就是一个存储数据的仓库,数据库本质上就是一个软件。一个程序

常见的数据库有哪些?

关系型数据库

MySQL、Oracle、DB2、SQL Server、Postgre SQL等

关系型数据库通常我们会创建很多个二维数据表

数据表之间相互关联起来,形成 一对一、一对多、多对多 等关系

之后可以利用SQL语句在多张表中查询我们所需的数据

支持事务,对数据的访问更加安全

非关系型数据库

MongoDB、Redis、Memcached、HBse 等

非关系型数据库的英文其实是 Mot only SQL,也简称为 NoSQL

相当于已非关系型数据库比较简单一些,存储数据也会更加自由(甚至我们可以直接将一个复杂的json对象直接塞入到数据库

中)

NoSQL 是基于 Key-Value 的对用关系,并且查询的过程中不需要经过 SQL 解析,所以性能更高

NoSQL 通常不支持事务,需要在自己的程序中来保证一些原子性的操作

开发中如何选择?

目前在公司进行后端开发(Node、Java、Go等),还是以关系型数据库为主

比较常用的用到菲关系型数据库的,在爬取大量数据进行存储时,会比较常见

认识 MySQL

MySQL 是一个关系型数据库,其实本质上就是一个软件、一个程序

这个程序中管理着多个数据库

每个数据库中可以有多张表

每个表可以有多条数据

查看数据库

show databases;

MySQL 默认的数据库:

infomation_schema:信息数据库,其中包括 MySQL 在维护的其他数据库、表、列、访问权限等信息

performance_schema:性能数据库,记录着 MySQL Server 数据库引擎在运行过程中的一些资源消耗相关的信息

mysql:用于存储数据库管理者的用户信息、权限信息以及一些日志信息等

sys:相当于是一个简易版的performance_schema,将性能数据库中的数据汇总成更容易理解的形式

创建数据库-表

#

创建数据库

create database coderhub;

#

查看数据库

show databases;

#

指定要使用的数据库

use coderhub;

#

查看当前正在使用的数据库

select database();

#

查看数据库中的表

show tables;

#

创建表

create table users(name varchar(10), age int, height double);

#

查看表中数据

select * from users;

#

向表中插入数据

insert into users (name, age, height) values ('kobe', 40, 1.98);

认识 SQL 语句

我们希望数据库(特别是在程序中),就需要有和数据库沟通的语言,这个言就是 SQL:

SQL 是 Structured Query Language,称之为结构化查询语言,简称 SQL

使用 SQL 遍写出来的语句,就称之为 SQL 语句

SQL 语句可以用于对数据库进行操作

事实上,常见的关系型数据库SQL语句都是比较相似的,所以你学会了MySQL 中的 SQL 语句,之后去操作比如 Oracle 或者其他的

关系型数据库,也是非常方便的

SQL 语句的常用规范:

通常关键字是大写的,比如

CREATE、TABLE、SHOW

一条语句结束后,需要以 ; 结尾

如果遇到关键性作为表名或者字段名称,可以用 `` 包裹

SQL 语句的分类:

常见的 SQL 语句分为4类

DDL (Data Definition Language):数据定义语言

可以通过 DDL 语句对数据库或者表进行:创建、删除、修改等操作

DML (Data Manipulation Language):数据操作语言

可以通过 DML 语句对表进行:添加、删除、修改等操作

DQL (Data Query Language):数据查询语言

可以通过 DQL 从数据库中查询记录(重点)

DCL (Data Control Language):数据控制语言

对数据库、表格的权限进行相关访问控制操作

数据库的操作

#

查看所有数据库

show databases;

#

选择某一个数据库

use coderhub;

#

查看当前正在使用的数据库

select database();

#

创建一个新的数据库

-- create database douyu;

#

首先判断数据库是否已存在,避免重复创建报错

create database if not exists douyu;

#

指定字符集

utf8mb4

、排序规则

utf8mb4_0900_ai_ci

create database if not exists huya default character set utf8mb4 collate utf8mb4_0900_ai_ci;

#

删除数据库

drop database if exists douyu;

#

修改数据库的编码

alter database huya character set = utf8 collate = utf8_unicode_ci;

数据表的操作

#

查看所有的表

show tables;

#

新建表

create table if not exists `students` (

`name` varchar(10),

`age` int,

`score` int

);

#

删除表

drop table if exists `moment`;

#

查看表的结构

desc `students`;

#

查看创建表的

SQL

语句

show create table `students`;

-- CREATE TABLE `students` (

-- `name` varchar(10) DEFAULT NULL,

-- `age` int DEFAULT NULL,

-- `score` int DEFAULT NULL

-- ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci

SQL 的数据类型

1. 数字类型

1. 整数数字类型:

INTEGER, INT, SMALLINT, TINYNT, MEDIUMINT, BIGINT

2. 浮点数字类型:

FLOAT, DOUBLE

(FLOAT 是 4 个字节,DOUBLE 是8个字节)

3. 精确数字类型:

DECIMAL, NUMERIC

(DECIMAL是NUMERIC的实现形式)

2. 日期和时间类型

1.

YEAR

YYYY

格式显示值,范围 1901到2155,和 0000

2.

DATE

类型用于具有日期部分但没有时间部分的值

1.

DATE

以格式

YYYY-MM-DD

显示值

2. 支持的范围是

1000-01-01

9999-12-31

3.

DATETIME

类型用于包含日期部分和时间部分的值

1.

DATETIME

以格式

YYYY-MM-DD hh:mm:ss

显示值

2. 支持的范围是

1000-01-01 00:00:00

9999-12-31 23:59:59

4.

TIMESTEMP

数据类型被用于包含时间和日期部分的值

1.

TIMESTAMP

以格式

YYYY-MM-DD hh:mm:ss

显示值

2. 但是它的范围是 UTC 的时间范围:**

1970-01-01 00:00:01

2038-01-19 03:14:07

**

另外:

DATETIME

TIMESTAMP

值可以包括在高达微秒(6位)精度的后小数秒一部分

比如

DATETIME

表示的范围可以是

1000-01-01 00:00:00.000000

9999-12-31 23:59:59.999999

3. 字符串(字符和字节)类型

1.

CHAR

类型在创建表时为固定长度,长度可以是0 到 255 之间的任何值

1. 在被查询时,会删除后面的空格

2.

VARCHAR

类型的值是可变长度的字符串,长度可以指定为 0 到 65535 之间的值

1. 在被查询时,不会删除后面的空格

3.

BINARY

VARBINARY

类型用于存储二进制字符串,存储的是字节字符串

4.

BLOB

用于存储大的二进制类型

5.

TEXT

用于存储大的字符类型

4. 空间类型

5. JSON 数据类型

表约束

主键

PRIMARY KEY

一张表中,我们为了区分每一条记录的唯一性,必须有一个字段永远不会重复,并且不会为空的,这个字段我们通常将它设置为主

键:

主键是表中唯一的索引

并且必须是

NOT NULL

的,如果没有设置

NOT NULL

,那么 MySQL 也会隐式的设置为

NOT NULL

主键也可以是多列索引,

PRIMARY KEY(key_part, ...)

,我们一般称之为联合主键

建议:开发中主键字段应该是和业务无关的,尽量不要使用业务字段来作为主键

唯一:

UNIQUE

create table if not exists `students` (

`name` varchar(10),

`age` int,

`score` int,

`height` decimal(10, 2),

`birthday` timestamp,

`phonenumber` varchar(20) unique

);

某些字段在开发中我们希望是唯一的,不会重复的,比如手机号码、身份证号码等,这个字段我们可以使用

UNIQUE

来约束

使用

UNIQUE

约束的字段在表中必须是不同的

对于所有引擎,

UNIQUE

索引允许

NULL

包含的列有多个值

NULL

不能为空:

NOT NULL

某些字段我们要求用户必须插入值,不可以为空,这个时候我们可以使用

NOT NULL

来约束

默认值:

DEFAULT

某些字段我们希望在没有设置值时给予一个默认值,这个时候我们可以使用

DEFAULT

来完成

自动递增:

AUTO_INCREMENT

某些字段我们希望不设置值时可以进行递增,比如用户的id,这个时候可以使用

AUTO_INCREMENT

来完成

外键约束也是最常用的一种约束手段

创建一个完整的表

use huya;

#

创建完整表的语法

create table if not exists `users` (

`id` int primary key auto_increment,

`name` varchar(20) not null,

`age` int default 0,

`phoneNum` varchar(20) unique default '',

`createTime` timestamp

);

#

修改表

# 1.

修改表的名字

alter table `users` rename to `user`;

# 2.

添加一个新的列

alter table `user` add `updateTime` timestamp;

# 3.

修改字段名称

alter table `user` change `phoneNum` `telPhone` varchar(20);

# 4.

修改字段的类型

alter table `user` modify `name` varchar(30);

# 5.

删除某一个字段

alter table `user` drop `age`;

#

补充

#

根据一个表结构去创建另外一张表

create table `user2` like `user`;

#

根据另外一个表中的所有内容创建一个新的表

create table `user3` (select * from `user`);

DML 对数据库进行增删改

# DML

#

插入数据

insert into `users` values(110, 'why', 18, '020-110110', '2020-10-20');

insert into `users` (`name`, `age`, `phoneNum`, `createTime`) values('kobi', 28, '000-111111', '2020-10-10');

insert into `users` (`name`, `phoneNum`) values('lilei', '000-111112');

#

需求

createTime

updateTime

可以自动设置值

alter table `users` modify `createTime` timestamp default current_timestamp;

#

修改完数据后,直接可以显示最新的更新时间

alter table `users` modify `updateTime` timestamp default current_timestamp on update current_timestamp;

insert into `users` (`name`, `phoneNum`) values('hanmeimei', '000-111113');

insert into `users` (`name`, `phoneNum`) values('lucy', '');

#

删除数据

# 1.

删除所有数据

-- delete from `users`;

# 2.

删除符合条件的数据

delete from `users` where id = 110;

#

更新数据

#

会修改表中所有的数据

-- update `users` set `name` = 'lily', `phoneNum` = '010-110110';

#

会修改符合条件的数据

update `users` set `name` = 'lily', `phoneNum` = '010-110110' where id = 111;

DQL 语句

DQL:Date Query Language(数据库查询语言)

SELETE

用于从一个或者多个表中检索选中的行(Record)

格式

SELECT select_expr [, select_expr]...

[FROM table_references]

[FROM table_references]

[WHERE where_condition]

[ORDER BY expr [ASC | DESC]]

[LIMIT {[offset, ] row_count | row_count OFFSET offset}]

[GROUP BY expr]

[HAVING where_condition]

基本查询

select * from `products`;

#

查询指定子弹

select title, price from `products`;

#

对字段结果起一个别名

select title as phoneTitle, price as currentPrise from `products`;

where

查询条件

WHERE

的比较运算符

# 1.

条件判断语句

#

案例:查询价格小于

1000

的手机

select * from `products` where price < 1000;

#

案例:价格等于

999

的手机

select * from `products` where price = 999;

#

案例:价格不等于

999

的手机

select * from `products` where price != 999;

select * from `products` where price <> 999;

#

案例:查询品牌是华为的手机

select * from `products` where brand = '华为';

WHERE

逻辑运算符

# 2.

逻辑运算语句

#

案例:价格大于

1000

小于

2000

的手机

select * from `products` where price > 1000 and price < 2000;

select * from `products` where price > 1000 && price < 2000;

# between and

包含等于

select * from `products` where price between 1000 and 2000;

#

案例:价格在

5000

以上或者品牌是华为的手机

select * from `products` where price > 5000 || brand = '华为';

select * from `products` where price > 5000 or brand = '华为';

#

将某些值设置为

NULL

update `products` set url = NULL where id >= 85 and id <= 88;

#

案例:查询某一个值为

NULL

select * from `products` where url is NULL;

select * from `products` where url = NULL;

#

案例:查询某一个值不为

NULL

select * from `products` where url is not NULL;

WHERE

模糊查询

模糊查询使用

LIKE

关键字,结合2个特殊符号:

%

表示匹配任意个的任意字符

_

表示匹配一个的任意字符

# 3.

模糊查询

#

案例:查询以

v

开头的

title

select * from `products` where title like 'v%';

#

案例:

title

字段里面

所有包含

M

字符的

select * from `products` where title like '%M%';

select * from `products` where title like '%P%';

#

案例:

title

字段里面

所有第二个字符包含

P

select * from `products` where title like '_P%';

# 4. IN

取多个值中的其中一个即可

select * from `products` where brand = '小米' or brand = '华为' or brand = '苹果';

select * from `products` where brand in ('华为', '小米', '苹果');

结果排序

#

按照价格的升序

select * from `products` where brand in ('华为', '小米', '苹果') order by price ASC;

#

按照价格

price

的升序,如果价格相同,再按照评分

score

的降序

select * from `products` where brand in ('华为', '小米', '苹果') order by price ASC, score DESC;

分页查询

#

格式

1

LIMIT limit OFFSET offset

#

格式

2

LIMIT limit, offset

# 0~20

select * from `products` limit 20 offset 0;

select * from `products` limit 0, 20;

# 21~40

select * from `products` limit 20 offset 20;

select * from `products` limit 20, 20;

# 41~60

select * from `products` limit 40, 20;

聚合函数:表示对值集合进行操作的组(集合)函数

# 1.

聚合函数的使用

#

求所有手机的价格的总和

select sum(price) from `products`;

-- select sum(price) totalPrice from `products`;

#

求一下华为手机价格的总和

select sum(price) from `products` where brand = '华为';

#

求华为手机的平均价格

select avg(price) from `products` where brand = '华为';

#

最高手机个最低手机的价格

select max(price) from `products`;

select min(price) from `products`;

#

求华为、苹果手机的个数

select count(*) from `products` where brand = '华为';

select count(url) from `products` where brand = '苹果';

#

不会将

url

字段为

null

的字段计算在内

select count(url) from `products` where brand = '苹果';

select count(price) from `products`;

#

价格重复的部不多次计数

select count(distinct price) from `products`;

分组

Group by

,通常和聚合函数一起使用,先分组,再进行聚合函数的计算

# 2.

分组

group by

的使用

#

根据品牌进行分组

展示不同品牌手机的平均价格

数量

评分

select brand, avg(price), count(*), avg(score) from `products` group by brand;

# 3. HAVING

的使用

#

所有品牌手机

平均价格大于

2000

select brand, avg(price) avgPrice, count(*), avg(score) from `products` group by brand having avgPrice > 2000;

# 4.

求评分

score > 7.5

的手机的平均价格

#

升级

平均分大于

7.5

分的手机,按照品牌进行分类,求出平均价格

select brand, avg(price) from `products` where score > 7.5 group by brand;

多表操作

外键

# 1.

创建

brand

表和插入数据

create table if not exists `brand` (

`id` int primary key auto_increment,

`name` varchar(20),

`website` varchar(100),

`phoneRank` int

);

insert into `brand` (name, website, phoneRank) values ('华为', '', 2);

insert into `brand` (name, website, phoneRank) values ('苹果', '', 10);

insert into `brand` (name, website, phoneRank) values ('小米', '', 5);

insert into `brand` (name, website, phoneRank) values ('oppo', '', 12);

insert into `brand` (name, website, phoneRank) values ('谷歌', '', 9);

insert into `brand` (name, website, phoneRank) values ('京东', '', 6);

# 2.

brand_id

设置引用

brand

中的

id

外键约束

#

添加一个

brand_id

的字段

alter table `products` add `brand_id` int;

-- alter table `products` drop `brand_id`;

#

修改

brand_id

为外键

alter table `products` add foreign key(brand_id) references brand(id);

#

设置

brand_id

的值

update `products` set `brand_id` = 1 where `brand` = '华为';

update `products` set `brand_id` = 2 where `brand` = '苹果';

update `products` set `brand_id` = 3 where `brand` = '小米';

update `products` set `brand_id` = 4 where `brand` = 'oppo';

# 3.

修改和删除外键引用的

id

#

报错

-- update `brand` set `id` = 100 where `id` = 1;

#

外键存在时更新和删除数据

# 4.

修改

brand_id

关联外键时的

action

# 4.1

获取到创建表时候的外键名称

show create table `products`;

# 4.2

根据名称将之前的外键删除

alter table `products` drop foreign key products_idfk_1;

# 4.3

重新添加外键约束

并设置新的

action

alter table `products` add foreign key(brand_id) references brand(id)

on update cascade

on delete restrict;

update `brand` set `id` = 100 where `id` = 1;

更新外键需要修改

on delete

或者

on update

的值

我们可以给更新或删除时设置以下几个值:

RESTRICT

(默认属性):当更新或删除某个记录时,会检查该记录是否有关联的外键记录,有的话会报错,不允许更新或删

NO ACTION

:和

RESTRICT

是一致的,是在 SQL 标准中定义的

CASCADE

:当更新或删除某个记录时,会检查该记录是否有关联的外键记录,有的话:

更新:那么会更新对应的记录

删除:那么关联的记录会一起被删除掉

SET NULL

:当更新或删除某个记录时,会检查该记录是否有关联的外键记录,有的话,将对应的值设置为

NULL

多表查询

默认多表查询的结果

第一张表 108 * 第二张表的 6 条数据

也就是说第一张表中的每一个数据,都会和第二张表中的咩一条数据结合一次

这个结果我们称之为 笛卡尔乘积,也称之为 直积,表示为 X*Y

但是事实上很多的数据是没有意义的,比如华为和苹果、小米的品牌结合起来就是没有意义的,我们可不可以进行筛选呢?

使用

where

来进行筛选

这个表示查询到笛卡尔乘积后的结果中,符合

_id =

条件的数据过滤出来

# 1.

获取到的是笛卡尔乘积

select * from `products`, `brand`;

#

获取到的是笛卡尔乘积进行筛选

select * from `products`, `brand` where _id = ;

多表之间的连接

左连接

右连接

内连接

全连接

# 2.

左连接

# 2.1

查询所有的手机以及对应的品牌

(包括没有品牌信息的手机)以及对应的品牌

null

select * from `products` left join `brand` on _id = ;

select * from `products` left outer join `brand` on _id = ;

# 2.2

查询没有对应品牌数据的手机

select * from `products` left join `brand` on _id = where is null;

# 3.

右链接

# 3.1

查询所有的品牌(没有对应的手机数据,品牌也显示)以及对应的手机数据

select * from `products` right join `brand` on _id = ;

select * from `products` right outer join `brand` on _id = ;

# 3.2

查询没有对应品牌数据的手机

select * from `products` right join `brand` on _id = where _id is null;

# 4.

内连接

# 4.1

查询所有带品牌数据的手机

select * from `products` join `brand` on _id = ;

select * from `products` join `brand` on _id = where price = 8699;

# 5.

全连接

# mysql

是不支持

full outer join

#

通过左连接和右链接联合来实现

(select * from `products` left join `brand` on _id = )

union

(select * from `products` right join `brand` on _id = );

-- select * from `products` full join `brand` on _id = ;

(select * from `products` left join `brand` on _id = where is null)

union

(select * from `products` right join `brand` on _id = where _id is null);

多对多关系

在开发中我们会遇到多对多的关系:

比如学生可以选择多门课程,一个课程可以被多个学生选择

#

基本数据的模拟

#

创建学生表

create table if not exists `students` (

create table if not exists `students` (

`id` int primary key auto_increment,

`name` varchar(20) not null,

`age` int

);

insert into `students` (name, age) values('why', 18);

insert into `students` (name, age) values('tom', 22);

insert into `students` (name, age) values('lilei', 25);

insert into `students` (name, age) values('lucy', 16);

insert into `students` (name, age) values('lily', 20);

#

创建课程表

create table if not exists `courses` (

`id` int primary key auto_increment,

`name` varchar(20) not null,

`price` double

);

insert into `courses` (name, price) values('英语', 100);

insert into `courses` (name, price) values('语文', 666);

insert into `courses` (name, price) values('数学', 888);

insert into `courses` (name, price) values('历史', 80);

insert into `courses` (name, price) values('物理', 888);

insert into `courses` (name, price) values('地理', 333);

# 2.

建立关系表

create table if not exists `students_select_courses`(

`id` int primary key auto_increment,

`student_id` int not null,

`course_id` int not null,

foreign key (student_id) references students(id) on update cascade,

foreign key (course_id) references courses(id) on update cascade

);

# 3.

学生选课

#

比如

why

学生选择了多门课程

英语、数学、历史

insert into `students_select_courses` (student_id, course_id) values(1, 1);

insert into `students_select_courses` (student_id, course_id) values(1, 3);

insert into `students_select_courses` (student_id, course_id) values(1, 4);

# lilei

选择了语文、历史

insert into `students_select_courses` (student_id, course_id) values(3, 2);

insert into `students_select_courses` (student_id, course_id) values(3, 4);

# lily

选择了语文、数学、历史

insert into `students_select_courses` (student_id, course_id) values(5, 2);

insert into `students_select_courses` (student_id, course_id) values(5, 3);

insert into `students_select_courses` (student_id, course_id) values(5, 4);

# 4.

查询需求

# 4.1

查询所有有选课的学生,选择了那些课程

#

内连接

# as

起别名

可省略

select stuId, stuName, stuAge, csId, csName, csPrice

from `students` stu

join `students_select_courses` ssc on = t_id

join `courses` cs on _id = ;

-- select * from `students` stu

-- join `students_select_courses` ssc on = t_id

-- join `courses` cs on _id = ;

-- select * from `students` as stu join `students_select_courses` as ssc on = t_id;

-- select * from `students` join `students_select_courses` on `students`.id = `students_select_courses`.student_id;

-- select * from `students` inner join `students_select_courses` on `students`.id = `students_select_courses`.student_id;

-- select * from `students` cross join `students_select_courses` on `students`.id = `students_select_courses`.student_id;

# 4.2

查询所有学生的选课情况

# 4.2

查询所有学生的选课情况

select stuId, stuName, stuAge, csId, csName, csPrice

from `students` stu

left join `students_select_courses` ssc on = t_id

left join `courses` cs on _id = ;

# 4.3

查询哪些学生没有选课

select stuId, stuName, stuAge, csId, csName, csPrice

from `students` stu

left join `students_select_courses` ssc on = t_id

left join `courses` cs on _id =

where is null;

# 4.4

查询哪些课没有被选择

select stuId, stuName, stuAge, csId, csName, csPrice

from `students` stu

right join `students_select_courses` ssc on = t_id

right join `courses` cs on _id =

where is null;

# 4.5

查询某一个学生选择了哪些课程

why

select stuId, stuName, stuAge, csId, csName, csPrice

from `students` stu

left join `students_select_courses` ssc on = t_id

left join `courses` cs on _id =

where = 1;

# tom

没有选课

select stuId, stuName, stuAge, csId, csName, csPrice

from `students` stu

left join `students_select_courses` ssc on = t_id

left join `courses` cs on _id =

where = 2;

# 5.

补充

/

扩展

# 5.1

将联合查询到的数据转成对象(一对多)

select stuId, stuName, stuAge,

json_object('id', , 'name', , 'price', )

from `students` stu

left join `students_select_courses` ssc on = t_id

left join `courses` cs on _id =

where = 1;

# {"id": 1, "name": "

英语

", "price": 100.0}

# 5.2

将查询到的多条数据,组织成对象,放入到一个数组中

(多对多)

select id, name, age,

json_arrayagg(json_object('id', , 'name', , 'price', ))

from `students` stu

join `students_select_courses` ssc on = t_id

join `courses` cs on _id =

group by ;

# [{"id": 1, "name": "

英语

", "price": 100.0}, {"id": 3, "name": "

数学

", "price": 888.0}, {"id": 4, "name": "

历史

", "price": 80.0}]

2023年12月8日发(作者:戏冰)

MySQL笔记(coderwhy老师Nodejs课程)

MySQL 笔记

数据库概述

数据库通俗来讲就是一个存储数据的仓库,数据库本质上就是一个软件。一个程序

常见的数据库有哪些?

关系型数据库

MySQL、Oracle、DB2、SQL Server、Postgre SQL等

关系型数据库通常我们会创建很多个二维数据表

数据表之间相互关联起来,形成 一对一、一对多、多对多 等关系

之后可以利用SQL语句在多张表中查询我们所需的数据

支持事务,对数据的访问更加安全

非关系型数据库

MongoDB、Redis、Memcached、HBse 等

非关系型数据库的英文其实是 Mot only SQL,也简称为 NoSQL

相当于已非关系型数据库比较简单一些,存储数据也会更加自由(甚至我们可以直接将一个复杂的json对象直接塞入到数据库

中)

NoSQL 是基于 Key-Value 的对用关系,并且查询的过程中不需要经过 SQL 解析,所以性能更高

NoSQL 通常不支持事务,需要在自己的程序中来保证一些原子性的操作

开发中如何选择?

目前在公司进行后端开发(Node、Java、Go等),还是以关系型数据库为主

比较常用的用到菲关系型数据库的,在爬取大量数据进行存储时,会比较常见

认识 MySQL

MySQL 是一个关系型数据库,其实本质上就是一个软件、一个程序

这个程序中管理着多个数据库

每个数据库中可以有多张表

每个表可以有多条数据

查看数据库

show databases;

MySQL 默认的数据库:

infomation_schema:信息数据库,其中包括 MySQL 在维护的其他数据库、表、列、访问权限等信息

performance_schema:性能数据库,记录着 MySQL Server 数据库引擎在运行过程中的一些资源消耗相关的信息

mysql:用于存储数据库管理者的用户信息、权限信息以及一些日志信息等

sys:相当于是一个简易版的performance_schema,将性能数据库中的数据汇总成更容易理解的形式

创建数据库-表

#

创建数据库

create database coderhub;

#

查看数据库

show databases;

#

指定要使用的数据库

use coderhub;

#

查看当前正在使用的数据库

select database();

#

查看数据库中的表

show tables;

#

创建表

create table users(name varchar(10), age int, height double);

#

查看表中数据

select * from users;

#

向表中插入数据

insert into users (name, age, height) values ('kobe', 40, 1.98);

认识 SQL 语句

我们希望数据库(特别是在程序中),就需要有和数据库沟通的语言,这个言就是 SQL:

SQL 是 Structured Query Language,称之为结构化查询语言,简称 SQL

使用 SQL 遍写出来的语句,就称之为 SQL 语句

SQL 语句可以用于对数据库进行操作

事实上,常见的关系型数据库SQL语句都是比较相似的,所以你学会了MySQL 中的 SQL 语句,之后去操作比如 Oracle 或者其他的

关系型数据库,也是非常方便的

SQL 语句的常用规范:

通常关键字是大写的,比如

CREATE、TABLE、SHOW

一条语句结束后,需要以 ; 结尾

如果遇到关键性作为表名或者字段名称,可以用 `` 包裹

SQL 语句的分类:

常见的 SQL 语句分为4类

DDL (Data Definition Language):数据定义语言

可以通过 DDL 语句对数据库或者表进行:创建、删除、修改等操作

DML (Data Manipulation Language):数据操作语言

可以通过 DML 语句对表进行:添加、删除、修改等操作

DQL (Data Query Language):数据查询语言

可以通过 DQL 从数据库中查询记录(重点)

DCL (Data Control Language):数据控制语言

对数据库、表格的权限进行相关访问控制操作

数据库的操作

#

查看所有数据库

show databases;

#

选择某一个数据库

use coderhub;

#

查看当前正在使用的数据库

select database();

#

创建一个新的数据库

-- create database douyu;

#

首先判断数据库是否已存在,避免重复创建报错

create database if not exists douyu;

#

指定字符集

utf8mb4

、排序规则

utf8mb4_0900_ai_ci

create database if not exists huya default character set utf8mb4 collate utf8mb4_0900_ai_ci;

#

删除数据库

drop database if exists douyu;

#

修改数据库的编码

alter database huya character set = utf8 collate = utf8_unicode_ci;

数据表的操作

#

查看所有的表

show tables;

#

新建表

create table if not exists `students` (

`name` varchar(10),

`age` int,

`score` int

);

#

删除表

drop table if exists `moment`;

#

查看表的结构

desc `students`;

#

查看创建表的

SQL

语句

show create table `students`;

-- CREATE TABLE `students` (

-- `name` varchar(10) DEFAULT NULL,

-- `age` int DEFAULT NULL,

-- `score` int DEFAULT NULL

-- ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci

SQL 的数据类型

1. 数字类型

1. 整数数字类型:

INTEGER, INT, SMALLINT, TINYNT, MEDIUMINT, BIGINT

2. 浮点数字类型:

FLOAT, DOUBLE

(FLOAT 是 4 个字节,DOUBLE 是8个字节)

3. 精确数字类型:

DECIMAL, NUMERIC

(DECIMAL是NUMERIC的实现形式)

2. 日期和时间类型

1.

YEAR

YYYY

格式显示值,范围 1901到2155,和 0000

2.

DATE

类型用于具有日期部分但没有时间部分的值

1.

DATE

以格式

YYYY-MM-DD

显示值

2. 支持的范围是

1000-01-01

9999-12-31

3.

DATETIME

类型用于包含日期部分和时间部分的值

1.

DATETIME

以格式

YYYY-MM-DD hh:mm:ss

显示值

2. 支持的范围是

1000-01-01 00:00:00

9999-12-31 23:59:59

4.

TIMESTEMP

数据类型被用于包含时间和日期部分的值

1.

TIMESTAMP

以格式

YYYY-MM-DD hh:mm:ss

显示值

2. 但是它的范围是 UTC 的时间范围:**

1970-01-01 00:00:01

2038-01-19 03:14:07

**

另外:

DATETIME

TIMESTAMP

值可以包括在高达微秒(6位)精度的后小数秒一部分

比如

DATETIME

表示的范围可以是

1000-01-01 00:00:00.000000

9999-12-31 23:59:59.999999

3. 字符串(字符和字节)类型

1.

CHAR

类型在创建表时为固定长度,长度可以是0 到 255 之间的任何值

1. 在被查询时,会删除后面的空格

2.

VARCHAR

类型的值是可变长度的字符串,长度可以指定为 0 到 65535 之间的值

1. 在被查询时,不会删除后面的空格

3.

BINARY

VARBINARY

类型用于存储二进制字符串,存储的是字节字符串

4.

BLOB

用于存储大的二进制类型

5.

TEXT

用于存储大的字符类型

4. 空间类型

5. JSON 数据类型

表约束

主键

PRIMARY KEY

一张表中,我们为了区分每一条记录的唯一性,必须有一个字段永远不会重复,并且不会为空的,这个字段我们通常将它设置为主

键:

主键是表中唯一的索引

并且必须是

NOT NULL

的,如果没有设置

NOT NULL

,那么 MySQL 也会隐式的设置为

NOT NULL

主键也可以是多列索引,

PRIMARY KEY(key_part, ...)

,我们一般称之为联合主键

建议:开发中主键字段应该是和业务无关的,尽量不要使用业务字段来作为主键

唯一:

UNIQUE

create table if not exists `students` (

`name` varchar(10),

`age` int,

`score` int,

`height` decimal(10, 2),

`birthday` timestamp,

`phonenumber` varchar(20) unique

);

某些字段在开发中我们希望是唯一的,不会重复的,比如手机号码、身份证号码等,这个字段我们可以使用

UNIQUE

来约束

使用

UNIQUE

约束的字段在表中必须是不同的

对于所有引擎,

UNIQUE

索引允许

NULL

包含的列有多个值

NULL

不能为空:

NOT NULL

某些字段我们要求用户必须插入值,不可以为空,这个时候我们可以使用

NOT NULL

来约束

默认值:

DEFAULT

某些字段我们希望在没有设置值时给予一个默认值,这个时候我们可以使用

DEFAULT

来完成

自动递增:

AUTO_INCREMENT

某些字段我们希望不设置值时可以进行递增,比如用户的id,这个时候可以使用

AUTO_INCREMENT

来完成

外键约束也是最常用的一种约束手段

创建一个完整的表

use huya;

#

创建完整表的语法

create table if not exists `users` (

`id` int primary key auto_increment,

`name` varchar(20) not null,

`age` int default 0,

`phoneNum` varchar(20) unique default '',

`createTime` timestamp

);

#

修改表

# 1.

修改表的名字

alter table `users` rename to `user`;

# 2.

添加一个新的列

alter table `user` add `updateTime` timestamp;

# 3.

修改字段名称

alter table `user` change `phoneNum` `telPhone` varchar(20);

# 4.

修改字段的类型

alter table `user` modify `name` varchar(30);

# 5.

删除某一个字段

alter table `user` drop `age`;

#

补充

#

根据一个表结构去创建另外一张表

create table `user2` like `user`;

#

根据另外一个表中的所有内容创建一个新的表

create table `user3` (select * from `user`);

DML 对数据库进行增删改

# DML

#

插入数据

insert into `users` values(110, 'why', 18, '020-110110', '2020-10-20');

insert into `users` (`name`, `age`, `phoneNum`, `createTime`) values('kobi', 28, '000-111111', '2020-10-10');

insert into `users` (`name`, `phoneNum`) values('lilei', '000-111112');

#

需求

createTime

updateTime

可以自动设置值

alter table `users` modify `createTime` timestamp default current_timestamp;

#

修改完数据后,直接可以显示最新的更新时间

alter table `users` modify `updateTime` timestamp default current_timestamp on update current_timestamp;

insert into `users` (`name`, `phoneNum`) values('hanmeimei', '000-111113');

insert into `users` (`name`, `phoneNum`) values('lucy', '');

#

删除数据

# 1.

删除所有数据

-- delete from `users`;

# 2.

删除符合条件的数据

delete from `users` where id = 110;

#

更新数据

#

会修改表中所有的数据

-- update `users` set `name` = 'lily', `phoneNum` = '010-110110';

#

会修改符合条件的数据

update `users` set `name` = 'lily', `phoneNum` = '010-110110' where id = 111;

DQL 语句

DQL:Date Query Language(数据库查询语言)

SELETE

用于从一个或者多个表中检索选中的行(Record)

格式

SELECT select_expr [, select_expr]...

[FROM table_references]

[FROM table_references]

[WHERE where_condition]

[ORDER BY expr [ASC | DESC]]

[LIMIT {[offset, ] row_count | row_count OFFSET offset}]

[GROUP BY expr]

[HAVING where_condition]

基本查询

select * from `products`;

#

查询指定子弹

select title, price from `products`;

#

对字段结果起一个别名

select title as phoneTitle, price as currentPrise from `products`;

where

查询条件

WHERE

的比较运算符

# 1.

条件判断语句

#

案例:查询价格小于

1000

的手机

select * from `products` where price < 1000;

#

案例:价格等于

999

的手机

select * from `products` where price = 999;

#

案例:价格不等于

999

的手机

select * from `products` where price != 999;

select * from `products` where price <> 999;

#

案例:查询品牌是华为的手机

select * from `products` where brand = '华为';

WHERE

逻辑运算符

# 2.

逻辑运算语句

#

案例:价格大于

1000

小于

2000

的手机

select * from `products` where price > 1000 and price < 2000;

select * from `products` where price > 1000 && price < 2000;

# between and

包含等于

select * from `products` where price between 1000 and 2000;

#

案例:价格在

5000

以上或者品牌是华为的手机

select * from `products` where price > 5000 || brand = '华为';

select * from `products` where price > 5000 or brand = '华为';

#

将某些值设置为

NULL

update `products` set url = NULL where id >= 85 and id <= 88;

#

案例:查询某一个值为

NULL

select * from `products` where url is NULL;

select * from `products` where url = NULL;

#

案例:查询某一个值不为

NULL

select * from `products` where url is not NULL;

WHERE

模糊查询

模糊查询使用

LIKE

关键字,结合2个特殊符号:

%

表示匹配任意个的任意字符

_

表示匹配一个的任意字符

# 3.

模糊查询

#

案例:查询以

v

开头的

title

select * from `products` where title like 'v%';

#

案例:

title

字段里面

所有包含

M

字符的

select * from `products` where title like '%M%';

select * from `products` where title like '%P%';

#

案例:

title

字段里面

所有第二个字符包含

P

select * from `products` where title like '_P%';

# 4. IN

取多个值中的其中一个即可

select * from `products` where brand = '小米' or brand = '华为' or brand = '苹果';

select * from `products` where brand in ('华为', '小米', '苹果');

结果排序

#

按照价格的升序

select * from `products` where brand in ('华为', '小米', '苹果') order by price ASC;

#

按照价格

price

的升序,如果价格相同,再按照评分

score

的降序

select * from `products` where brand in ('华为', '小米', '苹果') order by price ASC, score DESC;

分页查询

#

格式

1

LIMIT limit OFFSET offset

#

格式

2

LIMIT limit, offset

# 0~20

select * from `products` limit 20 offset 0;

select * from `products` limit 0, 20;

# 21~40

select * from `products` limit 20 offset 20;

select * from `products` limit 20, 20;

# 41~60

select * from `products` limit 40, 20;

聚合函数:表示对值集合进行操作的组(集合)函数

# 1.

聚合函数的使用

#

求所有手机的价格的总和

select sum(price) from `products`;

-- select sum(price) totalPrice from `products`;

#

求一下华为手机价格的总和

select sum(price) from `products` where brand = '华为';

#

求华为手机的平均价格

select avg(price) from `products` where brand = '华为';

#

最高手机个最低手机的价格

select max(price) from `products`;

select min(price) from `products`;

#

求华为、苹果手机的个数

select count(*) from `products` where brand = '华为';

select count(url) from `products` where brand = '苹果';

#

不会将

url

字段为

null

的字段计算在内

select count(url) from `products` where brand = '苹果';

select count(price) from `products`;

#

价格重复的部不多次计数

select count(distinct price) from `products`;

分组

Group by

,通常和聚合函数一起使用,先分组,再进行聚合函数的计算

# 2.

分组

group by

的使用

#

根据品牌进行分组

展示不同品牌手机的平均价格

数量

评分

select brand, avg(price), count(*), avg(score) from `products` group by brand;

# 3. HAVING

的使用

#

所有品牌手机

平均价格大于

2000

select brand, avg(price) avgPrice, count(*), avg(score) from `products` group by brand having avgPrice > 2000;

# 4.

求评分

score > 7.5

的手机的平均价格

#

升级

平均分大于

7.5

分的手机,按照品牌进行分类,求出平均价格

select brand, avg(price) from `products` where score > 7.5 group by brand;

多表操作

外键

# 1.

创建

brand

表和插入数据

create table if not exists `brand` (

`id` int primary key auto_increment,

`name` varchar(20),

`website` varchar(100),

`phoneRank` int

);

insert into `brand` (name, website, phoneRank) values ('华为', '', 2);

insert into `brand` (name, website, phoneRank) values ('苹果', '', 10);

insert into `brand` (name, website, phoneRank) values ('小米', '', 5);

insert into `brand` (name, website, phoneRank) values ('oppo', '', 12);

insert into `brand` (name, website, phoneRank) values ('谷歌', '', 9);

insert into `brand` (name, website, phoneRank) values ('京东', '', 6);

# 2.

brand_id

设置引用

brand

中的

id

外键约束

#

添加一个

brand_id

的字段

alter table `products` add `brand_id` int;

-- alter table `products` drop `brand_id`;

#

修改

brand_id

为外键

alter table `products` add foreign key(brand_id) references brand(id);

#

设置

brand_id

的值

update `products` set `brand_id` = 1 where `brand` = '华为';

update `products` set `brand_id` = 2 where `brand` = '苹果';

update `products` set `brand_id` = 3 where `brand` = '小米';

update `products` set `brand_id` = 4 where `brand` = 'oppo';

# 3.

修改和删除外键引用的

id

#

报错

-- update `brand` set `id` = 100 where `id` = 1;

#

外键存在时更新和删除数据

# 4.

修改

brand_id

关联外键时的

action

# 4.1

获取到创建表时候的外键名称

show create table `products`;

# 4.2

根据名称将之前的外键删除

alter table `products` drop foreign key products_idfk_1;

# 4.3

重新添加外键约束

并设置新的

action

alter table `products` add foreign key(brand_id) references brand(id)

on update cascade

on delete restrict;

update `brand` set `id` = 100 where `id` = 1;

更新外键需要修改

on delete

或者

on update

的值

我们可以给更新或删除时设置以下几个值:

RESTRICT

(默认属性):当更新或删除某个记录时,会检查该记录是否有关联的外键记录,有的话会报错,不允许更新或删

NO ACTION

:和

RESTRICT

是一致的,是在 SQL 标准中定义的

CASCADE

:当更新或删除某个记录时,会检查该记录是否有关联的外键记录,有的话:

更新:那么会更新对应的记录

删除:那么关联的记录会一起被删除掉

SET NULL

:当更新或删除某个记录时,会检查该记录是否有关联的外键记录,有的话,将对应的值设置为

NULL

多表查询

默认多表查询的结果

第一张表 108 * 第二张表的 6 条数据

也就是说第一张表中的每一个数据,都会和第二张表中的咩一条数据结合一次

这个结果我们称之为 笛卡尔乘积,也称之为 直积,表示为 X*Y

但是事实上很多的数据是没有意义的,比如华为和苹果、小米的品牌结合起来就是没有意义的,我们可不可以进行筛选呢?

使用

where

来进行筛选

这个表示查询到笛卡尔乘积后的结果中,符合

_id =

条件的数据过滤出来

# 1.

获取到的是笛卡尔乘积

select * from `products`, `brand`;

#

获取到的是笛卡尔乘积进行筛选

select * from `products`, `brand` where _id = ;

多表之间的连接

左连接

右连接

内连接

全连接

# 2.

左连接

# 2.1

查询所有的手机以及对应的品牌

(包括没有品牌信息的手机)以及对应的品牌

null

select * from `products` left join `brand` on _id = ;

select * from `products` left outer join `brand` on _id = ;

# 2.2

查询没有对应品牌数据的手机

select * from `products` left join `brand` on _id = where is null;

# 3.

右链接

# 3.1

查询所有的品牌(没有对应的手机数据,品牌也显示)以及对应的手机数据

select * from `products` right join `brand` on _id = ;

select * from `products` right outer join `brand` on _id = ;

# 3.2

查询没有对应品牌数据的手机

select * from `products` right join `brand` on _id = where _id is null;

# 4.

内连接

# 4.1

查询所有带品牌数据的手机

select * from `products` join `brand` on _id = ;

select * from `products` join `brand` on _id = where price = 8699;

# 5.

全连接

# mysql

是不支持

full outer join

#

通过左连接和右链接联合来实现

(select * from `products` left join `brand` on _id = )

union

(select * from `products` right join `brand` on _id = );

-- select * from `products` full join `brand` on _id = ;

(select * from `products` left join `brand` on _id = where is null)

union

(select * from `products` right join `brand` on _id = where _id is null);

多对多关系

在开发中我们会遇到多对多的关系:

比如学生可以选择多门课程,一个课程可以被多个学生选择

#

基本数据的模拟

#

创建学生表

create table if not exists `students` (

create table if not exists `students` (

`id` int primary key auto_increment,

`name` varchar(20) not null,

`age` int

);

insert into `students` (name, age) values('why', 18);

insert into `students` (name, age) values('tom', 22);

insert into `students` (name, age) values('lilei', 25);

insert into `students` (name, age) values('lucy', 16);

insert into `students` (name, age) values('lily', 20);

#

创建课程表

create table if not exists `courses` (

`id` int primary key auto_increment,

`name` varchar(20) not null,

`price` double

);

insert into `courses` (name, price) values('英语', 100);

insert into `courses` (name, price) values('语文', 666);

insert into `courses` (name, price) values('数学', 888);

insert into `courses` (name, price) values('历史', 80);

insert into `courses` (name, price) values('物理', 888);

insert into `courses` (name, price) values('地理', 333);

# 2.

建立关系表

create table if not exists `students_select_courses`(

`id` int primary key auto_increment,

`student_id` int not null,

`course_id` int not null,

foreign key (student_id) references students(id) on update cascade,

foreign key (course_id) references courses(id) on update cascade

);

# 3.

学生选课

#

比如

why

学生选择了多门课程

英语、数学、历史

insert into `students_select_courses` (student_id, course_id) values(1, 1);

insert into `students_select_courses` (student_id, course_id) values(1, 3);

insert into `students_select_courses` (student_id, course_id) values(1, 4);

# lilei

选择了语文、历史

insert into `students_select_courses` (student_id, course_id) values(3, 2);

insert into `students_select_courses` (student_id, course_id) values(3, 4);

# lily

选择了语文、数学、历史

insert into `students_select_courses` (student_id, course_id) values(5, 2);

insert into `students_select_courses` (student_id, course_id) values(5, 3);

insert into `students_select_courses` (student_id, course_id) values(5, 4);

# 4.

查询需求

# 4.1

查询所有有选课的学生,选择了那些课程

#

内连接

# as

起别名

可省略

select stuId, stuName, stuAge, csId, csName, csPrice

from `students` stu

join `students_select_courses` ssc on = t_id

join `courses` cs on _id = ;

-- select * from `students` stu

-- join `students_select_courses` ssc on = t_id

-- join `courses` cs on _id = ;

-- select * from `students` as stu join `students_select_courses` as ssc on = t_id;

-- select * from `students` join `students_select_courses` on `students`.id = `students_select_courses`.student_id;

-- select * from `students` inner join `students_select_courses` on `students`.id = `students_select_courses`.student_id;

-- select * from `students` cross join `students_select_courses` on `students`.id = `students_select_courses`.student_id;

# 4.2

查询所有学生的选课情况

# 4.2

查询所有学生的选课情况

select stuId, stuName, stuAge, csId, csName, csPrice

from `students` stu

left join `students_select_courses` ssc on = t_id

left join `courses` cs on _id = ;

# 4.3

查询哪些学生没有选课

select stuId, stuName, stuAge, csId, csName, csPrice

from `students` stu

left join `students_select_courses` ssc on = t_id

left join `courses` cs on _id =

where is null;

# 4.4

查询哪些课没有被选择

select stuId, stuName, stuAge, csId, csName, csPrice

from `students` stu

right join `students_select_courses` ssc on = t_id

right join `courses` cs on _id =

where is null;

# 4.5

查询某一个学生选择了哪些课程

why

select stuId, stuName, stuAge, csId, csName, csPrice

from `students` stu

left join `students_select_courses` ssc on = t_id

left join `courses` cs on _id =

where = 1;

# tom

没有选课

select stuId, stuName, stuAge, csId, csName, csPrice

from `students` stu

left join `students_select_courses` ssc on = t_id

left join `courses` cs on _id =

where = 2;

# 5.

补充

/

扩展

# 5.1

将联合查询到的数据转成对象(一对多)

select stuId, stuName, stuAge,

json_object('id', , 'name', , 'price', )

from `students` stu

left join `students_select_courses` ssc on = t_id

left join `courses` cs on _id =

where = 1;

# {"id": 1, "name": "

英语

", "price": 100.0}

# 5.2

将查询到的多条数据,组织成对象,放入到一个数组中

(多对多)

select id, name, age,

json_arrayagg(json_object('id', , 'name', , 'price', ))

from `students` stu

join `students_select_courses` ssc on = t_id

join `courses` cs on _id =

group by ;

# [{"id": 1, "name": "

英语

", "price": 100.0}, {"id": 3, "name": "

数学

", "price": 888.0}, {"id": 4, "name": "

历史

", "price": 80.0}]

与本文相关的文章

发布评论

评论列表 (0)

  1. 暂无评论