Mysql数据库

Mysql数据库

zy123
2025-03-21 /  0 评论 /  0 点赞 /  0 阅读 /  7425 字
最近更新于 04-03

Mysql数据库

安装启动Mysql

mysql

  • 是 MySQL 的命令行客户端工具,用于连接、查询和管理 MySQL 数据库。
  • 你可以通过它来执行 SQL 命令、查看数据和管理数据库。

mysqld

  • 是 MySQL 服务器守护进程,也就是 MySQL 数据库的实际运行程序。
  • 它负责处理数据库的存储、查询、并发访问、用户验证等核心任务。

添加环境变量:

'\path\to\mysql-8.0.31-winx64\bin\'目录添加到 PATH 环境变量中,便于命令行操作。

启动Mysql

net start mysql  // 启动mysql服务
net stop mysql  // 停止mysql服务

修改root账户密码

mysqladmin -u root password 123456

本地windows下的账号:root 密码: 123456

登录

mysql -u用户名 -p密码 [-h数据库服务器的IP地址 -P端口号] 
mysql -uroot -p123456 

-h 参数不加,默认连接的是本地 127.0.0.1 的MySQL服务器

-P 参数不加,默认连接的端口号是 3306

图形化工具

推荐Navicat

Mysql简介

通用语法

1、SQL语句可以单行或多行书写,以分号结尾

2、SQL语句可以使用空格/缩进来增强语句的可读性。因为SQL语句在执行时,数据库会忽略额外的空格和换行符

SELECT 
    name, 
    age, 
    address
FROM 
    users
WHERE 
    age > 18;

3、MySQL数据库的SQL语句不区分大小写

4、注释:

  • 单行注释:-- 注释内容 或 # 注释内容(MySQL特有)
  • 多行注释: /* 注释内容 */

分类

分类 全称 说明
DDL Data Definition Language 数据定义语言,用来定义数据库对象(数据库,表,字段)
DML Data Manipulation Language 数据操作语言,用来对数据库表中的数据进行增删改
DQL Data Query Language 数据查询语言,用来查询数据库中表的记录
DCL Data Control Language 数据控制语言,用来创建数据库用户、控制数据库的访问权限

数据类型

字符串类型

CHAR(n):声明的字段如果数据类型为char,则该字段占据的长度固定为声明时的值,例如:char(4),存入值 'ab',其长度仍为4.

VARCHAR(n):varchar(100)表示最多可以存100个字符,每个字符占用的字节数取决于所使用的字符集。存储开销:除了存储实际数据外,varchar 类型还会额外存储 1 或 2 个字节来记录字符串的长度。

TEXT:用于存储大文本数据,存储长度远大于 VARCHAR,但不支持索引整列内容(通常索引长度有限制)。

日期时间类型:

类型 大小 范围 格式 描述
DATE 3 1000-01-01 至 9999-12-31 YYYY-MM-DD 日期值
TIME 3 -838:59:59 至 838:59:59 HH:MM:SS 时间值或持续时间
DATETIME 8 1000-01-01 00:00:00 至 9999-12-31 23:59:59 YYYY-MM-DD HH:MM:SS 混合日期和时间值

注意:字符串和日期时间型数据在 SQL 语句中应包含在引号内,例如:'2025-03-29''hello'

数值类型

类型 大小 有符号(SIGNED)范围 无符号(UNSIGNED)范围 描述
TINYINT 1byte (-128,127) (0,255) 小整数值
INT/INTEGER 4bytes (-2^31,2^31-1) (0,2^32-1) 大整数值
FLOAT 4bytes (-3.402823466 E+38,3.402823466351 E+38) 0 和 (1.175494351 E-38,3.402823466 E+38) 单精度浮点数值
DECIMAL 依赖于M(精度)和D(标度)的值 依赖于M(精度)和D(标度)的值 小数值(精确定点数)

DECIMAL(M, D):定点数类型,M 表示总位数,D 表示小数位数,适合存储精度要求较高的数值(如金钱)。

DDL

数据库操作

查询所有数据库:

show databases;

创建一个itcast数据库。

create database itcast;

切换到itcast数据

use itcast;

查询当前正常使用的数据库:

select database();

删除itcast数据库

drop database if exists itcast; -- itcast数据库存在时删除,不存在也不报错

表操作

查询当前数据库下所有表

show tables;

查看指定表的结构(字段)

desc tb_tmps;  ( tb_tmps为表名)

创建表

通常一个列定义的顺序如下:

  1. 列名(字段)
  2. 字段类型
  3. 可选的字符集或排序规则(如果需要)
  4. 约束:例如 NOT NULLUNIQUEPRIMARY KEYDEFAULT
  5. 特殊属性:例如 AUTO_INCREMENT
  6. 注释:例如 COMMENT '说明'
create table  表名(
	字段1  字段1类型 [约束]  [comment  '字段1注释' ],
	字段2  字段2类型 [约束]  [comment  '字段2注释' ],
	......
	字段n  字段n类型 [约束]  [comment  '字段n注释' ] 
) [ comment  '表注释' ] ;

注意: [ ] 中的内容为可选参数; 最后一个字段后面没有逗号

eg:

image-20220829143005524

create table tb_user (
    id int comment 'ID,唯一标识',   # id是一行数据的唯一标识(不能重复)
    username varchar(20) comment '用户名',
    name varchar(10) comment '姓名',
    age int comment '年龄',
    gender char(1) comment '性别'
) comment '用户表';

约束

约束 描述 关键字
非空约束 限制该字段值不能为null not null
唯一约束 保证字段的所有数据都是唯一、不重复的 unique
主键约束 主键是一行数据的唯一标识,要求非空且唯一 primary key
默认约束 保存数据时,如果未指定该字段值,则采用默认值 default
外键约束 让两张表的数据建立连接,保证数据的一致性和完整性 foreign key
CREATE TABLE tb_user (
    id INT PRIMARY KEY AUTO_INCREMENT COMMENT 'ID,唯一标识', 
    username VARCHAR(20) NOT NULL UNIQUE COMMENT '用户名',
    name VARCHAR(10) NOT NULL COMMENT '姓名',
    age INT COMMENT '年龄',
    gender CHAR(1) DEFAULT '男' COMMENT '性别'
) COMMENT '用户表';

-- 假设我们有一个 orders 表,它将 tb_user 表的 id 字段作为外键
CREATE TABLE orders (
    order_id INT PRIMARY KEY AUTO_INCREMENT COMMENT '订单ID',
    order_date DATE COMMENT '订单日期',
    user_id INT,
    FOREIGN KEY (user_id) REFERENCES tb_user(id) 
    ON DELETE CASCADE
    ON UPDATE CASCADE,
    COMMENT '订单表'
);

foreign key:

  • 保证数据的一致性和完整性

  • ON DELETE CASCADE:如果父表中的某行被删除,那么子表中所有与之关联的行也会被自动删除。

    ON DELETE SET NULL:如果父表中的某行被删除,子表中的相关外键列会被设置为 NULL

    ON UPDATE CASCADE:如果父表中的外键值被更新,那么子表中的相关外键值也会自动更新。

注意:在实际的 Java 项目中,特别是在一些微服务架构或分布式系统中,通常不直接依赖数据库中的外键约束。相反,开发者通常会在代码中通过逻辑来确保数据的一致性和完整性。

auto_increment:

  • 每次插入新的行记录时,数据库自动生成id字段(主键)下的值
  • 具有auto_increment的数据列是一个正数序列且整型(从1开始自增)
  • 不能应用于多个字段

设计表的字段时,还应考虑:

id:主键,唯一标志这条记录 create_time :插入记录的时间 now()函数可以获取当前时间 update_time:最后修改记录的时间

DML(增删改)

DML英文全称是Data Manipulation Language(数据操作语言),用来对数据库中表的数据记录进行增、删、改操作。

  • 添加数据(INSERT)
  • 修改数据(UPDATE)
  • 删除数据(DELETE)

INSERT

insert语法:

  • 指定字段添加数据

    insert into 表名 (字段名1, 字段名2) values (值1, 值2);
    
  • 全部字段添加数据

    insert into 表名 values (值1, 值2, ...);
    
  • 批量添加数据(指定字段)

    insert into 表名 (字段名1, 字段名2) values (值1, 值2), (值1, 值2);
    
  • 批量添加数据(全部字段)

    insert into 表名 values (值1, 值2, ...), (值1, 值2, ...);
    

UPDATE

update语法:

update 表名 set 字段名1 = 值1 , 字段名2 = 值2 , .... [where 条件] ;

案例1:将tb_emp表中id为1的员工,姓名name字段更新为'张三'

update tb_emp set name='张三',update_time=now() where id=1;

案例2:将tb_emp表的所有员工入职日期更新为'2010-01-01'

update tb_emp set entrydate='2010-01-01',update_time=now();

**注意!**不带where会更新表中所有记录!

DELETE

delete语法:

delete from 表名  [where  条件] ;

案例1:删除tb_emp表中id为1的员工

delete from tb_emp where id = 1;

案例2:删除tb_emp表中所有员工(记录)

delete from tb_emp;

DELETE 语句不能删除某一个字段的值(可以使用UPDATE,将该字段值置为NULL即可)。

DQL(查询)

DQL英文全称是Data Query Language(数据查询语言),用来查询数据库表中的记录。

查询关键字:SELECT

查询操作是所有SQL语句当中最为常见,也是最为重要的操作。

语法

SELECT
	字段列表
FROM
	表名列表                ----基本查询
WHERE
	条件列表                ----条件查询
GROUP  BY
	分组字段列表 
HAVING
	分组后条件列表            ----分组查询
ORDER BY
	排序字段列表              ----排序查询
LIMIT
	分页参数                 ----分页查询

基本查询

  • 查询多个字段

    select 字段1, 字段2, 字段3 from  表名;
    
  • 查询所有字段(通配符)

    select *  from  表名;
    
  • 设置别名

    select 字段1 [ as 别名1 ] , 字段2 [ as 别名2 ]  from  表名;
    
  • 去除重复记录

    select distinct 字段列表 from  表名;
    eg:select distinct job from tb_emp;
    

条件查询

比较运算符 功能
between ... and ... 在某个范围之内(含最小、最大值)
in(...) 在in之后的列表中的值,多选一
like 占位符 模糊匹配(_匹配单个字符, %匹配任意个字符)
is null 是null
= 等于
逻辑运算符 功能
and 或 && 并且 (多个条件同时成立)
or 或 || 或者 (多个条件任意一个成立)
not 或 ! 非 , 不是

表数据

id name gender job entrydate
1 张三 2 2 2005-04-15
2 李四 1 3 2007-07-22
3 王五 2 4 2011-09-01
4 赵六 1 2 2008-06-11

案例1:查询 入职时间 在 '2000-01-01' (包含) 到 '2010-01-01'(包含) 之间 且 性别为女 的员工信息

select *
from tb_emp
where entrydate between '2000-01-01' and '2010-01-01'
      and gender = 2;

案例2:查询 职位是 2 (讲师), 3 (学工主管), 4 (教研主管) 的员工信息

select *
from tb_emp
where job in (2,3,4);

案例3:查询 姓名 为两个字的员工信息

常见的 LIKE 模式匹配符包括:

%:表示零个或多个字符。

_:表示一个字符。

select *
from tb_emp
where name like '__';  # 通配符 "_" 代表任意1个字符

聚合函数

之前我们做的查询都是横向查询,就是根据条件一行一行的进行判断,而使用聚合函数查询就是纵向查询,它是对一列的值进行计算,然后返回一个结果值。(将一列数据作为一个整体,进行纵向计算)

聚合函数:

函数 功能
count 统计数量
max 最大值
min 最小值
avg 平均值
sum 求和

语法:

select  聚合函数(字段名、列名)  from  表名 ;

注意 : 聚合函数会忽略空值,对NULL值不作为统计。

# count(*)  推荐此写法(MySQL底层进行了优化)
select count(*) from tb_emp;   -- 统计记录数

SELECT SUM(amount) FROM tb_sales; -- 统计amount列的总金额

分组查询

分组: 按照某一列或者某几列,把相同的数据进行合并输出。

分组其实就是按列进行分类(指定列下相同的数据归为一类),然后可以对分类完的数据进行合并计算。

分组查询通常会使用聚合函数进行计算。

select  字段列表  from  表名  [where 条件]  group by 分组字段名  [having 分组后过滤条件];

orders表:

customer_id amount
1 100
1 200
2 150
2 300

例如,假设我们有一个名为 orders 的表,其中包含 customer_idamount 列,我们想要计算每个客户的订单总金额,可以这样写查询:

SELECT customer_id, SUM(amount) AS total_amount
FROM orders
GROUP BY customer_id;

在这个例子中,GROUP BY customer_id 将结果按照 customer_id 列的值进行分组,并对每个客户的订单金额求和,生成每个客户的总金额。

SELECT customer_id, SUM(amount) AS total_amount
FROM orders
GROUP BY customer_id
HAVING total_amount > specified_amount;

在这个查询中,HAVING 子句用于筛选出消费金额(total_amount)大于指定数目(specified_amount)的记录。你需要将 specified_amount 替换为你指定的金额数目。

注意事项:

​ • 分组之后,查询的字段一般为聚合函数和分组字段,查询其他字段无任何意义

​ • 执行顺序:where > 聚合函数 > having

排序查询

语法:

select  字段列表  
from   表名   
[where  条件列表] 
[group by  分组字段 ] 
order  by  字段1  排序方式1 , 字段2  排序方式2 … ;
  • 排序方式:

    • ASC :升序(默认值)

    • DESC:降序

select id, username, password, name, gender, image, job, entrydate, create_time, update_time
from tb_emp
order by entrydate ASC; -- 按照entrydate字段下的数据进行升序排序

分页查询

select  字段列表  from   表名  limit  起始索引, 每页显示记录数 ;

前端传过来的一般是页码,要计算起始索引

注意事项:

  1. 起始索引从0开始。 计算公式 : 起始索引 = (查询页码 - 1)* 每页显示记录数

  2. 分页查询是数据库的方言,不同的数据库有不同的实现,MySQL中是LIMIT

  3. 如果查询的是第一页数据,起始索引可以省略,直接简写为 limit 条数

多表设计

外键约束

外键约束的语法:

-- 创建表时指定
CREATE TABLE child_table (
    id INT PRIMARY KEY, 
    parent_id INT,  -- 外键字段
    FOREIGN KEY (parent_id) 
        REFERENCES parent_table (id)
        ON DELETE CASCADE   -- 可选,表示父表数据删除时,子表数据也会删除
        ON UPDATE CASCADE   -- 可选,表示父表数据更新时,子表数据会同步更新
);


-- 建完表后,添加外键
ALTER TABLE child_table
ADD CONSTRAINT fk_parent_id   -- 外键约束的名称,可选
FOREIGN KEY (parent_id)
REFERENCES parent_table (id)
ON DELETE CASCADE
ON UPDATE CASCADE;

一对多

image-20221206230156403

一对多关系实现:在数据库表中多的一方,添加外键字段(如dept_id),来关联'一'这方的主键(id)。

一对一

一对一关系表在实际开发中应用起来比较简单,通常是用来做单表的拆分。一对一的应用场景: 用户表=》基本信息表+身份信息表,以此来提高数据的操作效率。

image-20221207105632634

  • 基本信息:用户的ID、姓名、性别、手机号、学历
  • 身份信息:民族、生日、身份证号、身份证签发机关,身份证的有效期(开始时间、结束时间)

一对一 :在任意一方加入外键,关联另外一方的主键,并且设置外键为唯一的(UNIQUE)

多对多

多对多的关系在开发中属于也比较常见的。比如:学生和老师的关系,一个学生可以有多个授课老师,一个授课老师也可以有多个学生。

image-20221207113341028

案例:学生与课程的关系

  • 关系:一个学生可以选修多门课程,一门课程也可以供多个学生选择

  • 实现关系:建立第三张中间表(选课表),中间表至少包含两个外键,分别关联两方主键

多表查询

分类

多表查询可以分为:

  1. 连接查询

    • 内连接:相当于查询A、B交集部分数据

    image-20221207165446062

  2. 外连接

    • 左外连接:查询左表所有数据(包括两张表交集部分数据)

    • 右外连接:查询右表所有数据(包括两张表交集部分数据)

  3. 子查询

内连接

隐式内连接语法:

select  字段列表   from   表1 , 表2   where  条件 ... ;

显式内连接语法:

select  字段列表   from   表1  [ inner ]  join 表2  on  连接条件 ... ;

[inner]可省略

案例:查询员工的姓名及所属的部门名称

  • 隐式内连接实现
select tb_emp.name , tb_dept.name -- 分别查询两张表中的数据
from tb_emp , tb_dept -- 关联两张表
where tb_emp.dept_id = tb_dept.id; -- 消除笛卡尔积
  • 显示内连接
select tb_emp.name , tb_dept.name
from tb_emp inner join tb_dept
on tb_emp.dept_id = tb_dept.id;

外连接

左外连接语法结构:

select  字段列表   from   表1  left  [ outer ]  join 表2  on  连接条件 ... ;

左外连接相当于查询表1(左表)的所有数据,当然也包含表1和表2交集部分的数据。

右外连接语法结构:

select  字段列表   from   表1  right  [ outer ]  join 表2  on  连接条件 ... ;

右外连接相当于查询表2(右表)的所有数据,当然也包含表1和表2交集部分的数据。

案例:查询部门表中所有部门的名称, 和对应的员工名称

-- 左外连接:以left join关键字左边的表为主表,查询主表中所有数据,以及和主表匹配的右边表中的数据
select emp.name , dept.name
from tb_emp AS emp left join tb_dept AS dept 
     on emp.dept_id = dept.id;

image-20221207181204792

子查询

SQL语句中嵌套select语句,称为嵌套查询,又称子查询。

SELECT  *  FROM   t1   WHERE  column1 =  ( SELECT  column1  FROM  t2 ... );

子查询外部的语句可以是insert / update / delete / select 的任何一个,最常见的是 select。

标量子查询

子查询返回的结果是单个值(数字、字符串、日期等),最简单的形式,这种子查询称为标量子查询。

常用的操作符: = <> > >= < <=

案例1:查询"教研部"的所有员工信息

可以将需求分解为两步:

  1. 查询 "教研部" 部门ID
  2. 根据 "教研部" 部门ID,查询员工信息
-- 1.查询"教研部"部门ID
select id from tb_dept where name = '教研部';    #查询结果:2
-- 2.根据"教研部"部门ID, 查询员工信息
select * from tb_emp where dept_id = 2;

-- 合并出上两条SQL语句
select * from tb_emp where dept_id = (select id from tb_dept where name = '教研部');

列子查询

子查询返回的结果是一列(可以是多行,即多条记录),这种子查询称为列子查询。

常用的操作符:

操作符 描述
IN 在指定的集合范围之内,多选一
NOT IN 不在指定的集合范围之内

案例:查询"教研部"和"咨询部"的所有员工信息

分解为以下两步:

  1. 查询 "销售部" 和 "市场部" 的部门ID
  2. 根据部门ID, 查询员工信息
-- 1.查询"销售部"和"市场部"的部门ID
select id from tb_dept where name = '教研部' or name = '咨询部';    #查询结果:3,2
-- 2.根据部门ID, 查询员工信息
select * from tb_emp where dept_id in (3,2);

-- 合并以上两条SQL语句
select * from tb_emp where dept_id in (select id from tb_dept where name = '教研部' or name = '咨询部');

行子查询

子查询返回的结果是一行(可以是多列,即多字段),这种子查询称为行子查询。

常用的操作符:= 、<> 、IN 、NOT IN

案例:查询与"韦一笑"的入职日期及职位都相同的员工信息

可以拆解为两步进行:

  1. 查询 "韦一笑" 的入职日期 及 职位
  2. 查询与"韦一笑"的入职日期及职位相同的员工信息
-- 查询"韦一笑"的入职日期 及 职位
select entrydate , job from tb_emp where name = '韦一笑';  #查询结果: 2007-01-01 , 2
-- 查询与"韦一笑"的入职日期及职位相同的员工信息
select * from tb_emp where (entrydate,job) = ('2007-01-01',2);

-- 合并以上两条SQL语句
select * from tb_emp where (entrydate,job) = (select entrydate , job from tb_emp where name = '韦一笑');

表子查询

子查询返回的结果是多行多列,常作为临时表,这种子查询称为表子查询。

案例:查询入职日期是 "2006-01-01" 之后的员工信息 , 及其部门信息

分解为两步执行:

  1. 查询入职日期是 "2006-01-01" 之后的员工信息
  2. 基于查询到的员工信息,在查询对应的部门信息
select * from emp where entrydate > '2006-01-01';

select e.*, d.* from (select * from emp where entrydate > '2006-01-01') e left join dept d on e.dept_id = d.id ;

事务

简而言之:事务是一组操作的集合,它是一个不可分割的工作单位。事务会把所有的操作作为一个整体一起向系统提交或撤销操作请求,即这些操作要么同时成功,要么同时失败。

手动提交事务使用步骤:

  • 第1种情况:开启事务 => 执行SQL语句 => 成功 => 提交事务
  • 第2种情况:开启事务 => 执行SQL语句 => 失败 => 回滚事务
-- 开启事务
start transaction ;

-- 删除学工部
delete from tb_dept where id = 1;

-- 删除学工部的员工
delete from tb_emp where dept_id = 1;
  • 上述的这组SQL语句,如果如果执行成功,则提交事务
-- 提交事务 (成功时执行)
commit ;
  • 上述的这组SQL语句,如果如果执行失败,则回滚事务
-- 回滚事务 (出错时执行)
rollback ;

面试题:事务有哪些特性?

  • 原子性(Atomicity):事务是不可分割的最小单元,要么全部成功,要么全部失败。
  • 一致性(Consistency):事务完成时,必须使所有的数据都保持一致状态。(部门和该部门下的员工数据全部删除)
  • 隔离性(Isolation):数据库系统提供的隔离机制,保证事务在不受外部并发操作影响的独立环境下运行(事务还没commit,那么别的窗口就看不到该修改 )。
  • 持久性(Durability):事务一旦提交或回滚,它对数据库中的数据的改变就是永久的。

事务的四大特性简称为:ACID

索引

索引(index):是帮助数据库高效获取数据的数据结构 。

创建索引

-- 添加索引
create index idx_sku_sn on tb_sku (sn);  #在添加索引时,也需要消耗时间

-- 查询数据(使用了索引)
select * from tb_sku where sn = '100000003145008';

查看索引

show  index  from  表名;

案例:查询 tb_emp 表的索引信息

show  index  from  tb_emp;

删除索引

drop  index  索引名  on  表名;

案例:删除 tb_emp 表中name字段的索引

drop index idx_emp_name on tb_emp;

优点:

  1. 提高数据查询的效率,降低数据库的IO成本。
  2. 通过索引列对数据进行排序,降低数据排序的成本,降低CPU消耗。

缺点:

  1. 索引会占用存储空间。
  2. 索引大大提高了查询效率,同时却也降低了insert、update、delete的效率。

因为插入一条数据,要重新维护索引结构

注意事项:

  • 主键字段,在建表时,会自动创建主键索引 (primarily key)

  • 添加唯一约束时,数据库实际上会添加唯一索引 (unique约束)

结构

musql默认采用B+树来作索引

采用二叉搜索树或者是红黑树来作为索引的结构有什么问题?

答案 最大的问题就是在数据量大的情况下,树的层级比较深,会影响检索速度。因为不管是二叉搜索数还是红黑数,一个节点下面只能有两个子节点。此时在数据量大的情况下,就会造成数的高度比较高,树的高度一旦高了,检索速度就会降低。

说明:如果数据结构是红黑树,那么查询1000万条数据,根据计算树的高度大概是23左右,这样确实比之前的方式快了很多,但是如果高并发访问,那么一个用户有可能需要23次磁盘IO,那么100万用户,那么会造成效率极其低下。所以为了减少红黑树的高度,那么就得增加树的宽度,就是不再像红黑树一样每个节点只能保存一个数据,可以引入另外一种数据结构,一个节点可以保存多个数据,这样宽度就会增加从而降低树的高度。这种数据结构例如BTree就满足。

下面我们来看看B+Tree(多路平衡搜索树)结构中如何避免这个问题:

image-20221208181315728

B+Tree结构:

  • 每一个节点,可以存储多个key(有n个key,就有n个指针)
  • 节点分为:叶子节点、非叶子节点
    • 叶子节点,就是最后一层子节点,所有的数据都存储在叶子节点上
    • 非叶子节点,不是树结构最下面的节点,用于索引数据,存储的的是:key+指针
  • 为了提高范围查询效率,叶子节点形成了一个双向链表,便于数据的排序及区间范围查询
© 版权声明
THE END
喜欢就支持一下吧
点赞 0 分享 收藏
评论 抢沙发
取消