MySQL
___软件系统需要存放大量的数据 这些数据通常是非常复杂和庞大的
文件系统的缺点:
- 很难以合适的方式组织数据
- 很难进行数据共享 比如一个数据库需要为多个程序服务
- 对数据进行增删改查中的复杂操作 保证单操作的原子性
常见数据库
- 关系型数据库: MySQL、Oracle、DB2、SQL Server、Postgre SQL等
- 关系型数据库通常我们会创建很多个二维数据表;
- 数据表之间相互关联起来,形成一对一、一对多、多对对等关系;
- 之后可以利用SQL语句在多张表中查询我们所需的数据;
- 支持事务,对数据的访问更加的安全;
- 非关系型数据库:MongoDB、Redis、Memcached、HBse等;
- 非关系型数据库的英文其实是Not only SQL,也简称为NoSQL;
- 非关系型数据库比较简单一些,存储数据也会更加自由(甚至我们可以直接将一个复杂的json对象直接塞入到数据库中)
- NoSQL是基于Key-Value的对应关系,并且查询的过程中不需要经过SQL解析,所以性能更高;
- NoSQL通常不支持事务,需要在自己的程序中来保证一些原子性的操作;
- 比较常用的用到非关系型数据库的,在爬取大量的数据进行存储时,会比较常见;
认识MySQL
MySQL是一个关系型数据库,其实本质上就是一款软件、一个程序:
这个程序中管理着多个数据库;
每个数据库中可以有多张表;
每个表中可以有多条数据;
起步
下载:https://dev.mysql.com/downloads/mysql/
————如果下载慢 复制下载链接使用迅雷下载 快的意想不到
服务->启动MySQL80
MySQL的连接操作
第一次执行mysql--version
会找不到指令
所以添加环境变量
- window中:
- 打开电脑环境变量配置 然后在系统配置中找到path 将mysql可执行地址放到path中就可以了 一般默认
C:\Program Files\MySQL\MySQL Server 8.0\bin
- 打开电脑环境变量配置 然后在系统配置中找到path 将mysql可执行地址放到path中就可以了 一般默认
在终端中连接mysql
mysql -uroot -p密码
或者 mysql -uroot -p 回车输入密码
使用 gitbash 来连接数据库要执行该指令
winpty mysql -uroot -p
查看默认数据库 show databases
- infomation_schema:信息数据库,其中包括MySQL在维护的其他数据库、表、列、访问权限等信息;
- performance_schema:性能数据库,记录着MySQL Server数据库引擎在运行 过程中的一些资源消耗相关的信息;
- mysql:用于存储数据库管理者的用户信息、权限信息以及一些日志信息等;
- sys:相当于是一个简易版的performance_schema,将性能数据库中的数据汇总成更容易理解的形式;
操作数据库
创建数据库
创建数据库
create database coderhub;
使用数据库
use coderhub;
创建一张表
1
2
3
4
5create table users(
name varchar(20),
age int,
height double
);插入数据
insert into users (name, age, height) values ('hyyp', 20, 1.88);
查询表中全部数据
select * from users
GUI工具
用 Navicat 就完事了 施展传统艺能
SQL语句
___和数据库沟通的语言 结构化查询语言 是Structured Query Language(SQL)
SQL语句的常用规范:
- 通常关键字是大写的,比如CREATE、TABLE、SHOW等等;
- 一条语句结束后,需要以
;
结尾; - 如果遇到关键字作为表明或者字段名称,可以使用``包裹;
分类
常见的SQL语句我们可以分成四类:
- DDL(Data Definition Language):数据定义语言;
- 可以通过DDL语句对数据库或者表进行:创建、删除、修改等操作;
- DML(Data Manipulation Language):数据操作语言;
- 可以通过DML语句对表 数据进行:添加、删除、修改等操作;
- DQL(Data Query Language):数据查询语言;
- 可以通过DQL从数据库中查询记录;(重点)
- DCL(Data Control Language):数据控制语言;
- 对数据库、表格的权限进行相关访问控制操作;
DDL语句
数据库操作
创建数据库
1
2
3
4
5
6
7
8
9
10
11
12
13
14# 查看所有的数据库
SHOW DATABASES;
# 选择某个数据库
USE coderhub;
# 查看当前使用的数据库
SELECT DATABASE();
# 新建数据库
-- CREATE DATABASE hyp;
-- CREATE DATABASE IF NOT EXISTS hyp;
CREATE DATABASE IF NOT EXISTS peng DEFAULT CHARACTER SET utf8mb4
COLLATE utf8mb4_0900_ai_ci;删除数据库
1 | # 删除数据库 |
- 修改数据库编码
1 | # 修改数据库的编码 |
数据表的操作
1 | # 查看所有表 |
SQL的数据类型
___MySQL支持的数据类型有:数字类型,日期和时间类型,字符串(字符和字节)类型,空间类型和 JSON数据类型。
数字类型
MySQL的数字类型有很多:
- 整数数字类型:INTEGER,INT,SMALLINT,TINYINT,MEDIUMINT,BIGINT;
- 浮点数字类型:FLOAT,DOUBLE(FLOAT是4个字节,DOUBLE是8个字节);
- 精确数字类型:DECIMAL,NUMERIC(DECIMAL是NUMERIC的实现形式);
- DECIMAL(有效数字数的精度,小数点后的位数)
日期类型
YEAR以YYYY格式显示值
- 范围 1901到2155,和 0000。
DATE类型用于具有日期部分但没有时间部分的值:
- DATE以格式YYYY-MM-DD显示值 ;
- 支持的范围是 ‘1000-01-01’ 到 ‘9999-12-31’;
DATETIME类型用于包含日期和时间部分的值
- DATETIME以格式’YYYY-MM-DD hh:mm:ss’显示值
- 支持的范围是1000-01-01 00:00:00到9999-12-31 23:59:59;
TIMESTAMP数据类型被用于同时包含日期和时间部分的值:
- TIMESTAMP以格式’YYYY-MM-DD hh:mm:ss’显示值
- 但是它的范围是UTC的时间范围:’1970-01-01 00:00:01’到’2038-01-19 03:14:07’;
DATETIME或TIMESTAMP 值可以包括在高达微秒(6位)精度的后小数秒一部分
字符串类型
- CHAR类型在创建表时为固定长度,长度可以设置0到255之间的任何值;
- 在被查询时,会删除后面的空格;
- VARCHAR类型的值是可变长度的字符串,长度可以指定为0到65535之间的值;(使用比较多)
- 在被查询时,不会删除后面的空格;
- BINARY和VARBINARY 类型用于存储二进制字符串,存储的是字节字符串;
- BLOB用于存储大的二进制类型
- TEXT用于存储大的字符串类型
表约束
主键:PRIMARY KEY
在一张表中,我们为了区分每一条记录的唯一性,必须有一个字段是永远不会重复,并且不会为空的,这个字段我们通常会将它设置为主键:
主键是表中唯一的索引;
并且必须是NOT NULL的,如果没有设置 NOT NULL,那么MySQL也会隐式的设置为NOT NULL;
主键也可以是多列索引,PRIMARY KEY(key_part, …),我们一般称之为联合主键;
建议:开发中主键字段应该是和业务无关的,尽量不要使用业务字段来作为主键
唯一:UNIQUE
- 某些字段在开发中我们希望是唯一的,不会重复的,比如手机号码、身份证号码等,这个字段我们可以使用UNIQUE来约束
- 使用UNIQUE约束的字段在表中必须是不同的
- 对于所有引擎,UNIQUE 索引允许NULL包含的列具有多个值NULL。
不能为空:NOT NULL
- 某些字段我们要求用户必须插入值,不可以为空,这个时候我们可以使用 NOT NULL 来约束;
默认值:DEFAULT
- 某些字段我们希望在没有设置值时给予一个默认值,这个时候我们可以使用 DEFAULT来完成
自动递增:AUTO_INCREMENT (一般用在数字类型)
- 某些字段我们希望不设置值时可以进行递增,比如用户的id,这个时候可以使用AUTO_INCREMENT来完成
创建一个完整的表
1 | CREATE TABLE IF NOT EXISTS `hypers`( |
修改表
1 | #1.修改表的名字 |
1 | #根据一个表结构创建另外一张表 |
createTime 和 updateTime 可以自动设置值:
1 | ALTER TABLE `ypeng` MODIFY `createTime` TIMESTAMP DEFAULT CURRENT_TIMESTAMP; |
DML语句
插入数据
1 | INSERT INTO `ypeng` VALUES (111,'HYP','4441','2020-11-11','2020-11-22'); |
删除数据
1 | # 删除数据 |
更新数据
1 | #更新数据. |
DQL语句
查询表中所有字段以及数据
SELECT * FROM products;
查询指定字段
SELECT title,price FROM products;
对字段结果起一个别名
SELECT title as phoneTitle,price as currentPrice FROM products;
where查询条件
条件判断语句
1 | #价格小于1000的手机 |
逻辑运算语句
1 | # 查询1000到2000之间 |
模糊查询
模糊查询使用LIKE关键字,结合两个特殊的符号:
%表示匹配任意个的任意字符;
_表示匹配一个的任意字符;
1 | # 查询所有以v开头的title |
IN表示取多个值中的其中一个
1 | 等价 |
结果排序
ASC:升序排列;
DESC:降序排列;
1 | SELECT * FROM `products` WHERE brand IN('华为','小米','苹果') |
分页查询
- [LIMIT {[offset,] row_count | row_count OFFSET offset}]
1 | # LIMIT limit OFFSET offset; |
聚合函数
聚合函数表示对值集合进行操作的组(集合)函数
例:
1 | #1.1求所有手机的价格的总和 |
聚合函数相当于默认将所有的数据分成了一组
GroupBy
- GROUP BY通常和聚合函数一起使用:
- 表示我们先对数据进行分组,再对每一组数据,进行聚合函数的计算;
1 | 以brand分组 计算平均价格 个数 平均评分 |
Group By的约束
使用HAVING关键字 对GroupBy查询到的结果添加一些约束可以使用HAVING
1
2平均价格大于2000的品牌
`SELECT brand,AVG(price) avgPrice,COUNT(*),AVG(score) FROM products GROUP BY brand HAVING avgPrice>2000;`而WHERE是对表进行筛选 比如
1
2需求:评分大于7.5的手机按照品牌分类求出平均价格
SELECT brand,AVG(price) FROM `products` WHERE score>7.5 GROUP BY brand;
多张表的创建
商品表中对应的品牌需要包含很多其他的信息 为了防止数据混乱以及冗余 使用单独的一张表来存放品牌的信息
- 创建品牌(brand)表:
1 | CREATE TABLE IF NOT EXISTS `brand`( |
- 插入数据
1 |
|
外键
将两张表联系起来,我们可以将products中的brand_id关联到brand中的id:
- 如果是创建表添加外键约束,我们需要在创建表的()最后添加如下语句;
FOREIGN KEY (brand_id) REFERENCES brand(id)
- 如果是表已经创建好,额外添加外键:
ALTER TABLE products ADD FOREIGN KEY (brand_id) REFERENCES brand(id)
关联:
1 | 设置brand_id的值 |
外键存在时更新和删除数据
如果products中引用的外键被更新了或者删除了,这个时候执行代码是报错的
有的时候我们希望可以更新
可以给更新或者删除时设置几个值:
RESTRICT(默认属性):当更新或删除某个记录时,会检查该记录是否有关联的外键记录,有的话会报错的,不允许更新或删除;
NO ACTION:和RESTRICT是一致的,是在SQL标准中定义的;
CASCADE:当更新或删除某个记录时,会检查该记录是否有关联的外键记录,有的话:
更新:那么会更新对应的记录;
删除:那么关联的记录会被一起删除掉;
SET NULL:当更新或删除某个记录时,会检查该记录是否有关联的外键记录,有的话,将对应的值设置为NULL;
修改外键的更新时动作:
查看表结构
SHOW CREATE TABLE products;
- 可以知道外键的名称是products_ibfk_1
删除之前的外键
ALTER TABLE products DROP FOREIGN KEY products_ibfk_1;
添加新的外键,并且设置新的action
1
2
3ALTER TABLE `products` ADD FOREIGN KEY (brand_id)
REFERENCES brand(id)
ON UPDATE CASCADE ON DELETE CASCADE;
多表查询
如果我们希望查询到产品的同时,显示对应的品牌相关的信息,因为数据是存放在两张表中,所以这个时候就需要进行多表查询。
默认的多表查询的结果
如果我们直接通过查询语句希望在多张表中查询到数据
SELECT * FROM products, brand;
得到的结果第一张表中每一个条数据,都会和第二张表中的每一条数据结合一次 这个结果我们称之为 笛卡尔乘积,也称之为直积,表示为 X*Y
我们可以使用where来筛选
SELECT * FROM products, brand WHERE products.brand_id = brand.id;
这个表示查询到笛卡尔乘积后的结果中,符合products.brand_id = brand.id条件的数据过滤出来
但是这种方式在真实开发中一般不做使用
多表之间连接
- 左连接
- 如果我们希望获取到的是左边所有的数据(以左表为主):
- 这个时候就表示无论左边的表是否有对应的brand_id的值对应右边表的id,左边的数据都会被查询出来;
- 这个也是开发中使用最多的情况,它的完整写法是LEFT [OUTER] JOIN,但是OUTER可以省略的;
1 | SELECT * FROM `products` LEFT JOIN `brand` ON `products`.brand_id = `brand`.id; |
- 右连接
- 如果我们希望获取到的是右边所有的数据(以右表为主)
- 这个时候就表示无论左边的表中的brand_id是否有和右边表中的id对应,右边的数据都会被查询出来;
- 右连接在开发中没有左连接常用,它的完整写法是RIGHT [OUTER] JOIN,但是OUTER可以省略的
1 | SELECT * FROM `products` RIGHT JOIN `brand` ON `products`.brand_id = `brand`.id; |
- 内连接
- 内连接是表示左边的表和右边的表都有对应的数据关联
1 | SELECT * FROM `products` JOIN `brand` ON products.brand_id=brand.id WHERE price =1499; |
我们会发现它和之前的下面写法是一样的效果:
1
SELECT * FROM `products`, `brand` WHERE `products`.brand_id = `brand`.id;
但是他们代表的含义并不相同:
SQL语句一:内连接,代表的是在两张表连接时就会约束数据之间的关系,来决定之后查询的结果;
SQL语句二:where条件,代表的是先计算出笛卡尔乘积,在笛卡尔乘积的数据基础之上进行where条件的筛选;
全连接
1
2
3
4
5
6
7(SELECT * FROM `products` LEFT JOIN `brand` ON products.brand_id=brand.id)
UNION
(SELECT * FROM `products` RIGHT JOIN `brand` ON products.brand_id=brand.id);
(SELECT * FROM `products` LEFT JOIN `brand` ON products.brand_id=brand.id WHERE brand.id IS NULL)
UNION
(SELECT * FROM `products` RIGHT JOIN `brand` ON products.brand_id=brand.id WHERE products.brand_id IS NULL)
多对多关系
看代码吧
1 | #两张基本表 |
查询数据 数据类型
核心 转成对象需要 JSON_OBJECT
方法 数组 JSON_ARRAYAGG
1 | # 将联合查询到的数据转成对象(一对多) |