MYSQL学习

orbisz2025/8/11后端学习MYSQL

一、MySQL是什么

  • MySQL 是一个数据管理系统,核心功能是管理数据库,一个 MySQL 环境下可管理多个数据库。
  • 遵循 “关系模型”,数据之间可通过 “主键 - 外键” 建立关联,同时支持 ACID 事务特性。
  • 其核心功能是存储、组织、管理数据:通过 “数据库 - 表 - 行 - 列” 的层级结构(关系模型),将数据结构化存储(例如用 “用户表” 存储用户信息,“订单表” 存储订单数据),并支持高效的查询、修改、删除等操作。

二、MySQL基本指令

(一)DDL(数据定义语言)

操作目的SQL语句说明
查看所有数据库show databases;列出当前 MySQL 环境下的所有数据库
进入指定数据库use 数据库名;切换到目标数据库,后续操作基于该数据库
查看数据库表show tables;列出当前数据库中的所有表
新建数据库create database 数据库名;创建一个新的空数据库
删除数据表drop table 表名;注意:此操作会永久删除表,需谨慎执行

(二)DML(数据操作语言)

1. 插入数据

-- 1. 指定字段插入(推荐,灵活性高)
insert into 表名 (字段1,字段2,...) value (数据1,数据2,...);

-- 2. 插入所有列数据(需按表中列的顺序填写数据)
insert into 表名 value(数据1,数据2,数据3,...);

-- 3. 批量插入多条数据
insert into 表名 
value (数据1-1,数据1-2,...),
      (数据2-1,数据2-2,...),
      (数据3-1,数据3-2,...);

2. 删除数据

-- 删除指定条件的数据(例:删除 student 表中姓名为“王刚”的记录)
delete from student where name='王刚';

3. 修改数据

-- 修改指定条件的数据(例:修改 student 表中姓名为“李白”的记录,将 age 改为 20)
update student set age=20 where name='李白';

(三)DQL(数据查询语言)

1. 基础查询

-- 1. 查询表中所有数据(不推荐在工作环境使用)
select * from student;

-- 2. 查询指定列数据(例:查询 student 表的 student_id 和 student_name 列)
select student_id, student_name from student;

注意事项
工作环境中尽量避免使用 * 查询,原因如下:

  • 数据安全:SELECT * 会无条件返回表中所有列。可能泄露敏感字段(如密码、手机号);
  • IO 消耗:会强制数据库读取表中所有列的数据,对于不必要的列会增加磁盘 IO 负担;
  • 网络消耗:多余数据传输会占用更多网络带宽。
  • 索引失效:无法利用 “覆盖索引” 优化,只能执行 “回表查询”,增加查询耗时。
  • 慢查询:大字段拖慢查询。

2. 列别名(AS 用法)

-- 使用 AS 给列起别名(若别名是关键字,可用着重号 `` 包裹)
select student_id as '学生ID', student_name as `name` from student;
  • SQL 关键字是数据库系统预定义的、具有特殊含义的单词,用于表示 SQL 语句的结构或操作。
  • 着重号是SQL中用于标识标识符的符号,告诉数据库:“包裹的内容是一个自定义名称,而非 SQL 关键字”,避免解析歧义。

3. 条件查询

-- 单条件查询(例:查询 student 表中姓名为“李四”的学生信息)
select student_id, student_name, birthday, gender from student 
where student_name='李四';

-- 多条件查询(AND 逻辑:同时满足)
select student_id, student_name, birthday, gender from student 
where student_name='李四' and student_id = 9;

-- 多条件查询(OR 逻辑:满足任一)
select student_id, student_name, birthday, gender from student 
where student_name='李四' or gender = '女';

4. IN 关键字(匹配多个值)

-- 1. 匹配指定集合中的值(例:查询 student_id 为 1、3、8、10、12 的学生)
SELECT * FROM student WHERE student_id IN (1,3,8,10,12);

-- 2. NOT IN 排除指定集合(例:查询 student_id 不在 1、3、8、10、12 中的学生)
SELECT * FROM student WHERE student_id NOT IN (1,3,8,10,12);

5. 模糊查询(LIKE 用法)

  • %:匹配任意长度的字符(包括 0 个);
  • _:匹配 exactly 1 个字符。
-- 1. 姓名以“张”开头(例:张三、张伟、张小明等)
SELECT * FROM student WHERE student_name LIKE '张%';

-- 2. 姓名是 3 个字(例:张三丰、李四海等)
SELECT * FROM student where student_name LIKE '___';

-- 3. 姓名是 2 个字且以“张”开头(例:张三、张伟等)
SELECT * FROM student WHERE student_name LIKE '张_';

-- 4. 姓名中包含“张”(例:张三、李张三、张四等)
SELECT * FROM student WHERE student_name LIKE '%张%';

-- 5. 名字中没有“张”字的学生
SELECT * FROM student WHERE student_name NOT LIKE '%张%';

若需要匹配的字符串中本身包含 % 或 _(如 “折扣率 80%”“型号 A_123”),直接使用会被当作通配符解析,需用转义符 \ 声明“这是普通字符,不是通配符”。

-- 解析:`\%` 表示“普通字符 %”,而非通配符 → 匹配“折扣 80%”“优惠 80%”等
SELECT product_name FROM product WHERE product_desc LIKE '%80\%'; 
注意事项
  1. 区分大小写(部分数据库)
  • MySQL 默认不区分大小写(如 LIKE 'Zhang%'LIKE 'zhang%' 效果一致);
  • 若需区分大小写,可使用 BINARY 关键字:
    SELECT student_name FROM student 
    WHERE BINARY student_name LIKE 'Zhang%'; -- 仅匹配“Zhang”开头(首字母大写)的姓名
    
  1. 性能影响
  • 模糊查询(尤其 % 开头,如 '%三')会导致数据库无法使用索引,只能全表扫描,数据量大时查询速度慢;
  • 优化建议:尽量用“前缀匹配”(如 '三%'),避免“%开头”的匹配;若需频繁模糊查询,可考虑数据库的“全文索引”(如 MySQL 的 FULLTEXT 索引)。
  1. 中文匹配问题
  • 确保数据库表的字符集为 utf8mb4gbk(支持中文),否则可能出现匹配失效;
  • 示例:若字符集为 latin1(不支持中文),LIKE '王%' 可能无法匹配中文“王磊”。

6. 排序(ORDER BY)

  • 升序:ASC(默认,可省略);
  • 降序:DESC(需显式指定)。
  • 排序字段:可以是表中的列名、表达式(如 SUM(score))或列的别名(如 AS 别名)。
-- 1. 单字段排序(例:按 student_id 降序查询)
SELECT * FROM student ORDER BY student_id DESC;

-- 2. 多字段排序(例:先按 student_name 升序,再按 student_id 降序)
-- 规则:先按第一个字段排序,第一个字段值相同时,再按第二个字段排序,以此类推。
SELECT * FROM student ORDER BY student_name ASC, student_id DESC;
-- 3. 排序字段可以是表达式或函数的计算结果,而非直接使用表中的列。(按 “字符串长度” 排序(使用 LENGTH() 函数))
-- 按姓名长度升序排列(短名字在前,长名字在后)
SELECT student_name FROM student ORDER BY LENGTH(student_name) ASC;
注意事项
  • MySQL 中,NULL 被视为 “最小值”,
  • 字符串排序默认按字符的 ASCII 码值排序(而非实际语义)

7. 部分查询(LIMIT)

语法格式说明适用场景
LIMIT N返回查询结果的前 N 条数据(从第 1 条开始,索引从 0 计算时对应 0~N-1获取 “Top N” 数据(如前 10 条、前 5 条)
LIMIT offset, Noffset 表示 “起始偏移量”(从 0 开始计数,即第 offset+1 条数据),N 表示 “返回的行数”分页查询(如第 2 页、第 3 页数据)
-- 1. 查询前 3 条数据(起始索引默认 0,可省略)
select * FROM student LIMIT 3;  -- 等价于 LIMIT 0, 3

-- 2. 查询第 4-7 条数据(起始索引 3,查询 4 条)
select * from student limit 3, 4;

-- 3. 明确查询前 3 条(显式写起始索引 0,可读性更高)
select * from student limit 0, 3;

注意事项

  • 若结果包含 NULL 值,LIMIT 会正常截取
  • LIMIT offset, N 中,offset 是 “起始位置的偏移量”,而非 “起始页码”,且从 0 开始计数:
    • offset=0 → 从第 1 条数据开始
    • offset=5 → 从第 6 条数据开始
    • 错误示例:若想查第 1 页(1~5 条),写 LIMIT 1, 5 会从第 2 条开始,导致第 1 条数据丢失,正确写法是 LIMIT 0, 5 或简化为 LIMIT 5。
  • 必须配合 ORDER BY 保证顺序稳定
深度分页

通常表现为 LIMIT 子句中 offset 数值很大。

执行逻辑:

  • 数据库需要先扫描并排序前 100000 + 10 = 100010 条数据;
  • 丢弃前 100000 条数据,仅返回最后 10 条;
  • 随着 offset 增大,扫描和排序的数据量线性增加,磁盘 IO 和内存消耗剧增,查询耗时会大幅上升(可能从毫秒级变为秒级)。

优化方案:

  • 基于 “索引有序性” 的定位查询:若表中存在唯一且有序的字段(如自增主键 id、创建时间 create_time 等,需有索引),可通过 “条件过滤” 直接定位到分页起始位置,替代 offset。
  • 借助 “覆盖索引” 减少数据扫描:若查询只需部分字段,可创建覆盖索引(包含查询所需的所有字段),让数据库无需访问表数据,直接通过索引返回结果,减少 IO 消耗。

8. 合并查询(UNION / UNION ALL)

关键字功能效率适用场景
UNION合并多个查询结果,并去重(整体去重)较低需避免重复结果时
UNION ALL合并多个查询结果,不做去重较高允许重复结果,追求效率

注意:合并的结果集列数必须相同(列类型可不同)。

-- 格式1:UNION(去重合并)
SELECT 字段1, 字段2 FROM1 [WHERE 条件]
UNION
SELECT 字段1, 字段2 FROM2 [WHERE 条件];

-- 格式2:UNION ALL(保留重复合并)
SELECT 字段1, 字段2 FROM1 [WHERE 条件]
UNION ALL
SELECT 字段1, 字段2 FROM2 [WHERE 条件];

注意事项

  • 多个 SELECT 语句返回的字段数量必须相同,否则会报错。
-- 错误:第一个查询返回2个字段,第二个返回1个字段
SELECT id, name FROM student
UNION
SELECT age FROM student;
  • 对应位置的字段类型需兼容(如 int 与 float 兼容,varchar 与 text 兼容),否则可能导致数据转换错误或结果不符合预期。
-- 正确:id(int)与 num(int)兼容,name(varchar)与 title(varchar)兼容
SELECT id, name FROM student
UNION
SELECT num, title FROM course;
  • 若需对合并后的结果排序或分页,需将合并查询作为子查询,在外层进行处理(ORDER BY 和 LIMIT 需写在最后)。
  • UNION 会对整个结果集进行去重(即所有字段完全相同的行才会被视为重复),而非单字段去重。
适用场景
  • 合并同一表中不同条件的结果
  • 合并不同表的同类数据
  • 当查询条件复杂且难以用 OR 合并时,可拆分为多个简单查询再合并。需求:查询 “(年龄 < 18 且成绩> 90)” 或 “(年龄 > 60 且成绩 < 60)” 的学生。
SELECT * FROM student WHERE age < 18 AND score > 90
UNION ALL  -- 已知两个条件无重叠,用 UNION ALL 提升性能
SELECT * FROM student WHERE age > 60 AND score < 60;

9. 结果去重(DISTINCT)

-- 例:查询 student 表中不重复的姓名(对结果集去重,非对表中字段去重)
SELECT DISTINCT name FROM student;

(四)嵌套查询与关联查询

1. 嵌套查询(子查询)

定义:一个查询语句中嵌套另一个查询(子查询结果作为主查询的条件或数据源)。

-- 场景1:查询有不及格成绩的学生信息(成绩 < 60 为不及格)
-- 方式一:多表关联 + DISTINCT 去重
SELECT DISTINCT * FROM student,score WHERE score.score < 60 and student.student_id = score.student_id;

-- 方式二:IN 子查询(更简洁)
SELECT student_name 
FROM student 
WHERE student_id IN (
    SELECT DISTINCT student_id 
    FROM score 
    WHERE score < 60
);

-- 场景2:查询总成绩最高的学生 ID(子查询作为临时表)
-- 注意:子查询作为表时,必须起别名(例:别名 a)
SELECT * 
FROM (
    SELECT student_id, SUM(score) as sumscore 
    FROM score 
    GROUP BY student_id 
) as a 
ORDER BY sumscore DESC 
LIMIT 1;

2. 关联查询

定义:当查询结果需要从多张表获取时,通过“关联条件”将表连接(常见:左连接、内连接、全外连接)。

-- 1. 左连接(LEFT JOIN)
-- 规则:以左表(student)为主表,显示左表所有数据;右表(score)仅显示匹配关联条件的数据(不匹配则为 NULL)
SELECT s.*, sc.* 
FROM student s 
LEFT JOIN score sc 
ON s.student_id = sc.student_id;
-- 执行逻辑:先将 student 表中的每一行都加入到结果集中,然后在 score 表中查找与 student 表当前行 student_id 匹配的行,
-- 如果找到,就将对应的成绩字段值填入结果集;如果没找到,成绩字段就填入 NULL。

-- 2. 内连接(INNER JOIN)
-- 规则:仅显示两张表中“满足关联条件”的数据(无匹配则不显示)
SELECT s.*, sc.* 
FROM student s 
INNER JOIN score sc 
ON s.student_id = sc.student_id;
-- 执行逻辑:数据库会逐行检查 student 表和 score 表中的记录,
-- 只有当 student 表中的 student_id 与 score 表中的 student_id 相等时,才会将这两条记录对应的字段组合成一行加入到结果集中。

-- 3. 全外连接(FULL JOIN)
-- 说明:MySQL 不原生支持 FULL JOIN,需借助 UNION 合并左连接和右连接结果
SELECT s.*, sc.* 
FROM student s 
LEFT JOIN score sc 
ON s.student_id = sc.student_id
UNION
SELECT s.*, sc.* 
FROM student s 
RIGHT JOIN score sc 
ON s.student_id = sc.student_id;
-- 执行逻辑:先获取左连接的结果,再获取右连接的结果,最后通过 UNION 合并,去除重复行(如果使用 UNION ALL 则保留重复行)。

s.* 表示获取别名为 s 的表中的所有字段。

注意事项

  • SQL 中判断 NULL 值不能用 =,需用 IS NULL(判断空)或 IS NOT NULL(判断非空)。
  • 关联条件应选择能准确反映表之间关系的字段,通常是主键 - 外键关系,否则可能导致结果错误或出现大量冗余数据。
  • 在关联条件字段上创建索引可以大大提高关联查询的性能。
  • 当涉及三个或更多表的关联查询时,需要合理安排表的连接顺序和关联条件。可以先确定主表,再逐步连接其他相关表,确保逻辑清晰,避免出现数据遗漏或错误。

三、数据库常用数据类型

数值类型

类型分类具体类型字节数取值范围(有符号)取值范围(无符号 UNSIGNED)核心用途
整数类型TINYINT1-128 ~ 1270 ~ 255存储状态(如 0=禁用、1=启用)、性别(0=女、1=男)等微小型整数
SMALLINT2-32768 ~ 327670 ~ 65535存储年龄(0-120)、少量数据的 ID(如分类 ID)
MEDIUMINT3-8388608 ~ 83886070 ~ 16777215存储中等规模的 ID(如百万级数据的用户 ID)
INT4-2147483648 ~ 21474836470 ~ 4294967295最常用,存储常规 ID(如订单 ID、用户 ID)、数量(如商品库存)
BIGINT8-9223372036854775808 ~ 92233720368547758070 ~ 18446744073709551615存储超大 ID(如分布式系统的全局 ID)、超大规模数据的计数
浮点数/定点数FLOAT4单精度,约 7 位小数精度-非精确计算场景(如科学数据、温度、湿度)
DOUBLE8双精度,约 15 位小数精度-较高精度的非精确计算(如身高、体重)
DECIMAL(M,D)M+2M=总位数(默认 10),D=小数位(默认 0)-精确计算场景(如金额、税率、价格,例 DECIMAL(10,2) 表示 0.00~9999999.99)

字符串类型

类型分类具体类型长度限制核心特点核心用途
短字符串CHAR(M)M=1~255(固定长度)存储时长度固定,不足补空格;查询效率高固定长度的短文本(如手机号 CHAR(11)、身份证号 CHAR(18)、性别标识)
VARCHAR(M)M=1~65535(可变长度)存储时按实际内容长度分配空间,节省存储长度不固定的短文本(如姓名 VARCHAR(50)、地址 VARCHAR(255)、邮箱)
长字符串TEXT0~65535 字节(约 64KB)普通长文本存储短文、评论、商品简介
MEDIUMTEXT0~16777215 字节(约 16MB)中等长度长文本存储文章内容、日志记录
LONGTEXT0~4294967295 字节(约 4GB)超长文本存储大型文档、视频字幕、海量日志
二进制字符串BLOB0~65535 字节(约 64KB)存储二进制数据(如小图片、图标)小型二进制文件(实际开发中更推荐存储文件路径,而非二进制本身)
MEDIUMBLOB0~16777215 字节(约 16MB)存储中等二进制数据中等大小二进制文件(如压缩包、中等图片)
LONGBLOB0~4294967295 字节(约 4GB)存储超大二进制数据大型二进制文件(如视频片段、高清图片)

日期与时间类型

类型分类具体类型字节数格式取值范围核心特点核心用途
日期时间类型DATE3YYYY-MM-DD1000-01-01 ~ 9999-12-31仅存储日期(年-月-日)存储生日、订单日期、活动开始日期
TIME3HH:MM:SS-838:59:59 ~ 838:59:59仅存储时间(时-分-秒),支持负数(时间差)存储时长、打卡时间(如 09:30:00)、时间间隔
DATETIME8YYYY-MM-DD HH:MM:SS1000-01-01 00:00:00 ~ 9999-12-31 23:59:59存储日期+时间,不受时区影响存储订单创建时间、用户注册时间、事件发生时间(需精确且固定)
TIMESTAMP4YYYY-MM-DD HH:MM:SS1970-01-01 00:00:01 ~ 2038-01-19 03:14:07存储日期+时间,受时区影响;支持自动更新存储最后修改时间(如 DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
YEAR1YYYY1901 ~ 2155仅存储年份,节省空间存储出生年份、产品生产年份

特殊类型

类型分类具体类型长度限制核心特点核心用途
枚举/集合类型ENUM1~2 字节(取决于选项数)仅能从预定义选项中选择一个值;存储为数字索引存储固定选项的单值(如性别 ENUM('男','女')、订单状态 ENUM('待支付','已完成')
SET1~8 字节(取决于选项数)可从预定义选项中选择多个值(最多 64 个)存储固定选项的多值(如兴趣爱好 SET('阅读','运动','音乐')、用户权限 SET('查询','编辑','删除')

注意事项:数据库优化之一是“选择合适的数据类型”,例如:

  • 存储性别用 tinyint(0=女,1=男)而非 varchar
  • 存储金额用 decimal 而非 double,避免精度丢失。

四、事务管理

(一)事务基本操作

事务是“不可分割的工作单位”,操作要么全执行,要么全回滚。MySQL 中事务需依赖 InnoDB 存储引擎(MyISAM 不支持事务)。

操作指令功能说明
start transaction开启事务(后续 DML 操作不会自动提交)
savepoint 保存点名设置事务保存点(用于回滚到指定步骤,而非全量回滚)
rollback to 保存点名回滚事务到指定保存点(保存点之后的操作会撤销)
rollback全量回滚事务(撤销所有未提交的操作)
commit提交事务(所有操作永久生效,无法回滚;提交后自动删除所有保存点)
release savepoint 保存点名称删除保存点(移除已创建的保存点,释放资源)
savepoint(保存点):

SAVEPOINT 通过自定义的名称设置一个存储点,如果当前事务已经有了一个同名的 SAVEPOINT ,那么旧的将会被替代。

ROLLBACK TO SAVEPOINT 子句可以将当前事务回退到自定义的存储点位置,而不会结束事务, InnoDB 不会释放内存中的行锁(对于新插入的行,其锁信息通过行数据中自带的 “事务 ID” 标识,而不会单独存储在内存中,当回滚到保存点时,这些新插入的行会被直接删除,其携带的锁信息自然消失(相当于释放锁)。), 存储点之后语句都会撤销执行,包括新设置的存储点,也同样会被删除。

RELEASE SAVEPOINT 子句,会从当前的事务 SAVEPOINT 集合中,移除指定名称的 SAVEPOINT 。.

回退事务

当执行回退事务时,通过指定保存点可以回退到指定的点。

提交事务

使用comit语句可以提交事务,当执行了commit语句后,会确认事务的变化、结束事务、删除保存点、释放锁,数据生效。当使用commit语句结束事务之后, 其他会话将可以查看到事务变化后的新数据。

如果不开始事务,默认情况下,DML操作是自动提交的,不能回滚。mysql 的事务需要存储引擎为innodb ,而myisam 不支持。

示例:事务操作流程

-- 1. 创建测试表
create table TEXT(
  id int,
  name VARCHAR(32)
);

-- 2. 开启事务
start TRANSACTION;

-- 3. 设置保存点 a
SAVEPOINT a;

-- 4. 执行 DML 操作(插入第一条数据)
INSERT INTO TEXT values(100,'tom');

-- 5. 设置保存点 b
SAVEPOINT b;

-- 6. 执行 DML 操作(插入第二条数据)
INSERT INTO TEXT values(200,'jack');

-- 7. 查看当前数据(此时数据未提交,仅当前会话可见)
select * from TEXT;  -- 结果:两条数据

-- 8. 回滚到保存点 b(撤销“插入 200,'jack'”的操作)
rollback to b;
select * from TEXT;  -- 结果:仅 100,'tom'

-- 9. 回滚到保存点 a(撤销“插入 100,'tom'”的操作)
rollback to a;
select * from TEXT;  -- 结果:空表

-- 10. (可选)提交事务(若执行 commit,后续无法回滚)
-- commit;

(二)事务隔离级别

1. 隔离级别作用

多个事务并发访问时,隔离级别用于控制“事务间数据可见性”,避免脏读、不可重复读、幻读等问题。

2. 三类常见问题

问题类型定义
脏读(Dirty Read)事务 A 读取了事务 B 尚未提交的修改(若 B 回滚,A 读取的是“无效数据”)
不可重复读(Non-repeatable Read)事务 A 同一查询多次执行,因事务 B 提交修改/删除,导致每次结果不同
幻读(Phantom Read)事务 A 同一查询多次执行,因事务 B 提交插入,导致每次结果行数不同

3. 隔离级别操作指令

-- 1. 查看当前会话隔离级别
select @@transaction_isolation;

-- 2. 查看系统全局隔离级别
select @@global.transaction_isolation;

-- 3. 设置当前会话隔离级别(例:设置为“读未提交”)
set session transaction isolation level read uncommitted;

-- 4. 设置系统全局隔离级别(例:设置为“读未提交”)
set global transaction isolation level read uncommitted;

4. 4 种隔离级别名称及含义

MySQL 支持 SQL 标准定义的 4 种隔离级别,按隔离程度从低到高排序:

隔离级别名称含义解决的问题
READ UNCOMMITTED(读未提交)事务可以读取其他事务未提交的修改(脏读)
READ COMMITTED(读已提交)事务只能读取其他事务已提交的修改,避免脏读脏读
REPEATABLE READ(可重复读)事务中多次读取同一数据的结果一致,避免不可重复读(MySQL 默认级别)脏读、不可重复读
SERIALIZABLE(可序列化)最高隔离级别,事务串行执行,避免幻读脏读、不可重复读、幻读

(三)事务 ACID 特性

事务必须满足以下 4 个特性,确保数据一致性和可靠性:

  1. 原子性(Atomicity):事务是一个 “不可分割的最小操作单元”,操作“要么全成,要么全败”;undo log(回滚日志) 保证
  2. 一致性(Consistency):事务执行前后,数据库从“一个一致性状态”切换到“另一个一致性状态”(例:转账前 A 有 100 元、B 有 50 元,转账后 A 50 元、B 100 元,总金额不变);依赖其他三大特性保证
  3. 隔离性(Isolation):多个并发事务互不干扰,每个事务看到的数据是“独立的”;依赖 锁机制 和 MVCC(多版本并发控制) 实现
  4. 持久性(Durability):事务提交后,对数据的修改是永久性的(即使数据库崩溃,数据也不会丢失)。依赖 redo log(重做日志) 实现

五、数据库面试常见问题

1. mb3 和 mb4 有什么区别?

  • 核心差异:mbm 表示 max(最大),b 表示 byte(字节),即 mb3 一个字符最多占 3 字节,mb4 最多占 4 字节;
  • 功能差异:mb4mb3 多 1 字节,可支持表情符号(如 😊),而 mb3 仅支持常规字符(英文 1 字节、阿拉伯语 2 字节、东亚语言 3 字节)。

2. 数据库连接命令是什么?

mysql -h 主机名 -P 端口号 -u 用户名 -p
  • 参数说明:
    • -h:指定 MySQL 服务器的地址(IP 或域名)。
    • -u:指定用户名(例:root 是 MySQL 超级用户);
    • -p:提示输入密码(输入命令后按回车,再输入密码即可登录)。

3. varchar 和 char 的区别?

对比维度VARCHARCHAR
存储方式可变长度,按实际数据长度存储固定长度,不足时用空格填充至指定长度
长度限制0-65535 字节(实际受行总长度限制)0-255 字节
存储空间额外占用 1-2 字节存储长度信息(记录实际长度)不额外占用空间,直接使用指定长度的空间
查询效率较低(需计算实际长度)较高(直接按固定长度读取)
尾部空格处理存储时会自动截断尾部空格存储时保留尾部空格,查询时会自动截断
适用场景长度不固定的字符串(如姓名、地址、描述)长度固定的字符串(如手机号、身份证号、性别)
示例VARCHAR(50) 存储 "张三" 占用 3 字节(含长度标识)CHAR(50) 存储 "张三" 占用 50 字节(补 48 个空格)
  • VARCHAR 更节省空间,适合存储长度差异较大的数据;CHAR 因长度固定,查询效率更高,但可能浪费空间。
  • 尾部空格处理是重要区别:VARCHAR 会自动去除插入时的尾部空格,而 CHAR 会保留空格但查询时自动截断(可能导致匹配问题)。
  • 选择时需平衡空间利用率和查询性能,根据数据长度是否固定来决定。
最近更新 2025/8/13 21:41:44