目录
前言
- MySQL的基础的使用、用户管理、基础和高级查询可以参考MySQL技术笔记-从基础配置到高级查询的全栈实战指南
一、建表范式
(一)范式等级说明
范式 | 说明 |
---|---|
1NF | 字段不可再分,每列都是原子值 |
2NF | 在满足1NF的基础上,消除部分依赖,非主键字段必须完全依赖于主键 |
3NF | 在满足2NF的基础上,消除传递依赖,非主键字段不能依赖于其他非主键字段 |
BCNF | 任何非主属性不能对候选键有部分依赖 |
4NF | 消除多值依赖 |
5NF | 消除连接依赖 |
实际开发中,满足第三范式(3NF) 即可应对大多数场景。
(二) 2NF 与 3NF 的区别
-
2NF:如果一张表中包含多种不同实体的属性,必须拆分为多张表。
-
3NF:在已拆分的基础上,确保一张表中只能包含另一张表的主键,不能有其他冗余信息。
二、 表基础管理
(一) 建库
建库语法
CREATE DATABASE [IF NOT EXISTS] <数据库名>
[[DEFAULT] CHARACTER SET <字符集名>]
[[DEFAULT] COLLATE <校对规则名>];
[]
表示可选项。IF NOT EXISTS
:假设库不存在,避免建库重名报错。CHARACTER SET
:指定表使用的字符集(存储字符串的方式)。- MySQL 8.0.26
- 默认字符集:
utf8mb4
- 特点:支持完整的Unicode字符,包括Emoji 和特殊符号,适合多语言环境,尤其是中文支持。
- 默认字符集:
- MySQL 5.x
- 默认字符集:通常为
latin1
或utf8
(非utf8mb4
) - 问题:
utf8
编码仅支持最多 3 字节的字符,无法存储 Emoji 或某些特殊汉字。
- 默认字符集:通常为
- MySQL 8.0.26
COLLATE
:指定排序规则。
库名命名规则
- 仅可以使用数字、字母、下划线,不能纯数字。
- 区分字母大小写。
- 具有唯一性。
- 不可使用MySQL命令或特殊字符。
CREATE DATABASE testdb;
CREATE DATABASE TESTDB;
CREATE DATABASE TESTDB; -- 报错
CREATE DATABASE IF NOT EXISTS testdb; -- 正常
常用命令
SHOW DATABASES; -- 查看库
USE 库名; -- 进入库
SELECT DATABASE(); -- 查看所在的库
DROP DATABASE IF EXISTS 库名; -- 删除库
修改数据库
ALTER DATABASE 数据库名{
[DEFAULT] CHARACTER SET <字符集名> |
[DEFAULT] COLLATE <校对规则名>};
(二)建表
建表语法
CREATE TABLE库名.表名(
表头名1 数据类型 [约束],
表头名2 数据类型 [约束],
表头名3 数据类型,…);
- 表必须存放在库里。
- 示例:
CREATE TABLE test.users (
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(50) NOT NULL,
age INT,
email VARCHAR(100) UNIQUE
);
相关命令
SHOW TABLES; -- 显示已有的表
DESC 库名.表名; -- 查看表头
SELECT * FROM 库名.表名; -- 查看表记录
DROP TABLE 库名.表名; -- 删除表
(三)修改表
语法格式
ALTER TABLE 库.表 操作命令;
操作命令
- ADD:添加新字段,一起添加多个字段使用,分隔
ADD
命令(FIRST
、AFTER
)。 - MODIFY:修改字段类型,也可修改字段的位置。
- CHANGE:修改字段名,也可以同时修改字段类型。
- RENAME:修改表名。
- DROP:删除字段,删除多个字段使用,分隔
DROP
命令。 - 示例:
- 添加列:
ALTER TABLE test.users ADD COLUMN phone VARCHAR(20) AFTER email;
- 修改列类型:
ALTER TABLE test.users MODIFY COLUMN age TINYINT;
- 修改列名和类型:
ALTER TABLE test.users CHANGE COLUMN name username VARCHAR(60);
- 删除列:
ALTER TABLE test.users DROP COLUMN phonenumber;
- 重命名表:
ALTER TABLE test.users RENAME TO test.user_info;
- 添加列:
(四)复制表
复制表结构及数据
CREATE TABLE 新表名 AS SELECT * FROM 原表名; -- 全部字段
CREATE TABLE 库.表 SELECT 列名 FROM 库.表 [WHERE 条件]; -- 指定字段
CREATE TABLE test.user_copy AS SELECT * FROM test.users;
- 注意:不会复制原表的索引和主键。
仅复制表结构
CREATE TABLE 库.表 LIKE 库.表;
CREATE TABLE test.user_structure LIKE test.users;
- 注意:会复制原表的索引、主键等结构。
三、表记录管理
(一)插入表记录
不指定列名插入记录(必须给所有列赋值)
INSERT INTO 库名.表名 VALUES(值列表); -- 插入1行
INSERT INTO 库名.表名 VALUES(值列表),(值列表)....; -- 插入多行
- 注意:值的顺序必须和表中列的顺序一致,且数据类型要匹配。
- 示例:
INSERT INTO testdb.users VALUES (1, 'Alice', 25, 'alice@example.com');
INSERT INTO testdb.users (name, age, email) VALUES ('Charlie', 28, 'charlie@example.com'), ('David', 35, 'david@example.com');
指定列名插入记录(仅须给指定列赋值)
INSERT INTO 库名.表名(列名列表) VALUES(值列表); -- 插入1行
INSERT INTO 库名.表名(列名列表) VALUES(值列表),(值列表)....; -- 插入多行
- 注意:列和值的顺序要一致;列名先后顺序不重要;没有赋值的列使用默认值、自增长结果赋值。
- 示例:
INSERT INTO test.users (name, age, email) VALUES ('Bob', 30, 'bob@example.com');
- 使用SELECT查询结果赋值:
INSERT INTO 库名.表名(字段列表) (SELECT 字段列表 FROM 库.表 WHERE 条件);
- 注意:SELECT查询语句的字段个数和顺序必须和INSERT语句字段顺序和个数一致。
- 示例:
INSERT INTO test.user_backup (name, age, email) SELECT name, age, email FROM test.users WHERE age > 30;
- 使用SET命令赋值:
INSERT INTO 库名.表名 SET 字段=值,字段=值,……;
- 示例:
INSERT INTO departments SET dept_name = "教研部"; INSERT INTO employees (name, hire_date) (SELECT name, hire_date FROM employees WHERE employee_id IN (1, 2));
(二)修改表记录
// 批量修改
UPDATE 库名.表名 SET 字段1=值,字段2=值;
// 仅修改与条件匹配的
UPDATE 库名.表名 SET 字段1=值,字段2=值 WHERE 条件;
- 示例:
UPDATE test.users SET password = "test1"; UPDATE test.users SET password = "test2" WHERE name = "root";
(三)删除表记录
DELETE FROM库名.表名WHERE条件; -- 仅删除与条件匹配的行
DELETE FROM库名.表名; -- 清空表记录
TRUNCATE TABLE库名.表名; -- 清空表记录
- 示例:
DELETE FROM test.users WHERE shell IS NULL; DELETE FROM test.users; TRUNCATE TABLE test.users;
TRUNCATE TABLE
不支持WHERE
条件。- 自增长列,
TRUNCATE
后从1开始;DELETE
继续编号。 TRUNCATE
不能回滚,DELETE
可以。TRUNCATE
效率略高于DELETE
。
四、表数据类型
MySQL 8支持以下数据类型:
(一)数值类型
- 整型:TINYINT、SMALLINT、MEDIUMINT、INT、BIGINT。
- 浮点型:FLOAT、DOUBLE。
- 定点型:DECIMAL(适合金额等精度要求高的场景)。
- 整型类型仅存储数值的整数部分,浮点类型存储有小数点的数。
- 示例:
CREATE TABLE test.finance ( company_name VARCHAR(100), daily_flow DECIMAL(10,2), quarterly_flow DECIMAL(15,2) );
(二)日期和时间类型
- DATE、TIME、YEAR、DATETIME、TIMESTAMP。
- 用于存储如生日、注册时间、出生年份、入职日期等。
- 其中,
DATETIME
和TIMESTAMP
可以存储精确到秒级别的时间戳,但它们在存储方式和范围上存在一些差异。 - 推荐使用
DATETIME
,避免TIMESTAMP
的2038年问题。 - 示例:
CREATE TABLE test.events ( event_name VARCHAR(100), event_date DATETIME );
(三)字符类型
- CHAR、VARCHAR、TEXT、BLOB用来存储如姓名、收货地址、工作单位、家庭地址等。
CHAR
和VARCHAR
用于存储短字符串,而TEXT
和BLOB
用于存储较长的文本和二进制数据。- CHAR类型:不够指定字符个数时在右边用空格补全字符个数,超出时无法写入数据。
- VARCHAR类型:按数据实际大小分配存储空间,字符个数超出时无法写入数据。
- 示例:
CREATE TABLE testdb.members ( name VARCHAR(50), gender ENUM('male', 'female'), hobbies SET('reading', 'sports', 'music') );
(四)枚举类型
- ENUM、SET分别用于枚举和集合类型数据的存储。
- ENUM类型:单选,字段值仅能在范围内选择1个值。
- 示例:
CREATE TABLE test.test3 ( name CHAR(5), gender ENUM("boy", "girl") );
- SET类型:多选,字段值能在范围内选择1个或多个值。
- 示例:
CREATE TABLE test.test4 ( name CHAR(5), gender ENUM("boy", "girl"), hobbies SET("eat", "game", "music") );
(五)布尔类型
- 包括
BOOL
、BOOLEAN
。
(六)JSON类型
- MySQL 8引入了
JSON
类型,用于存储和处理JSON格式的数据。
(七)空间类型
- 包括
GEOMETRY
、POINT
、LINESTRING
、POLYGON
等。
(八)自定义类型
- 通过
CREATE TYPE
语句创建的自定义类型。
(九)支持多种扩展数据类型
- 如数组、XML和GIS等。
五、表数据批量处理
(一)检索目录
默认目录
SHOW VARIABLES LIKE "secure_file_priv";
操作步骤
- 创建目录并修改所有者及组。
- 修改主配置文件并重启服务。
#创建并修改目录属性 mkdir /myload chown mysql:mysql /test #修改配置文件 vim /etc/my.cnf.d/mysql-server.cnf #配置内容 [mysqld] secure_file_priv = "/test" #重启服务 systemctl restart mysqld
(二)数据导入
操作步骤
- 建表。
- 拷贝文件到检索目录。
- 导入数据。
语法格式
LOAD DATA INFILE "/目录名/文件名" INTO TABLE 库名.表名
FIELDS TERMINATED BY "分隔符"
LINES TERMINATED BY "\n";
(三)数据导出
语法格式
SELECT命令 INTO OUTFILE "/目录名/文件名";
SELECT命令 INTO OUTFILE "/目录名/文件名"
FIELDS TERMINATED BY "分隔符"
LINES TERMINATED BY "\n";
六、表头约束
(一)约束介绍
- 约束是一种限制,设置在字段上,用来控制字段的赋值。
- 类型:
- NOT NULL:非空,用于保证该字段的值不能为空。
- DEFAULT:默认值,用于保证该字段有默认值。
- UNIQUE:唯一索引,用于保证该字段的值具有唯一性,可以为空。
- PRIMARY KEY:主键,用于保证该字段的值具有唯一性并且非空。
- FOREIGN KEY:外键,用于限制两个表的关系,用于保证该字段的值必须来自于主表的关联列的值,在从表添加外键约束,用于引用主表中某些的值。
(二)查看约束
DESC 库.表;
(三)基本约束
NOT NULL
- 不允许赋空值。
CREATE TABLE test.test6 ( name CHAR(12) NOT NULL, class CHAR(5) NULL ); DESC test.test6;
DEFAULT
- 不给字段赋值时,使用默认值赋值。
CREATE TABLE test.test7 ( name CHAR(12) NOT NULL, class CHAR(5) NULL DEFAULT "TEST" ); DESC test.test7;
UNIQUE
- 字段的值不允许重复。
CREATE TABLE test.test8 ( name CHAR(12) NOT NULL, class CHAR(5) NULL DEFAULT "TEST", phonenumber CHAR(11), UNIQUE (phonenumber) ); DESC test.test8;
(四)高级约束
PRIMARY KEY
使用规则
- 字段值不允许重复,不允许赋NULL值。
- 一个表中只能有一个PRIMARY KEY字段。
- 多个字段做主键,称为复合主键,必须一起创建。
- 主键标志为
PRI
。 - 主键通常与
AUTO_INCREMENT
连用。 - 通常把表中唯一标识记录的字段设置为主键(如行号字段)。
创建主键
CREATE TABLE test.test9 (
stu_id INT PRIMARY KEY,
name CHAR(6) NOT NULL,
class CHAR(5) NULL,
phonenumber CHAR(11)
);
DESC test.test9;
删除/添加
ALTER TABLE test.test9 DROP PRIMARY KEY; -- 删除
ALTER TABLE test.test9 ADD PRIMARY KEY(stu_id); -- 添加
复合主键
- 多个字段一起做主键,复合主键的值不允许同时重复。
- 语法格式:
CREATE TABLE 库.表( 字段列表, PRIMARY KEY(字段名列表) );
- 示例:
CREATE TABLE test.test10 ( cip CHAR(15), port INT, status ENUM("allow", "deny"), PRIMARY KEY (cip, port) ); DESC test.test10;
AUTO_INCREMENT
- 通过字段自加1计算结果赋值。
- 语法格式:
CREATE TABLE库.表( 字段名 类型 PRIMARY KEY AUTO_INCREMENT, 字段名 类型,…… );
- 示例:
CREATE TABLE test.test11 ( id INT PRIMARY KEY AUTO_INCREMENT, name CHAR(8), class CHAR(5), age INT ); DESC test11;
FOREIGN KEY
- 插入记录时,字段值在另一个表的字段值范围内选择。
使用规则
- 表存储引擎必须是
InnoDB
。 - 字段类型要一致。
- 被参照字段必须是索引类型的一种(如
PRIMARY KEY
)。
创建外键
CREATE TABLE库.表名(
字段列表,
FOREIGN KEY(字段名)
REFERENCES 库.表名(字段名) # 指定外键
ON UPDATE CASCADE # 同步更新
ON DELETE CASCADE # 同步删除
) ENGINE=InnoDB; # 指定存储引擎
查看外键
SHOW CREATE TABLE库.表 \G
SELECT * FROM information_schema.table_constraints WHERE table_name = '表名';
删除外键
ALTER TABLE 库.表 DROP FOREIGN KEY 外键名;
添加外键
ALTER TABLE 库.表 ADD FOREIGN KEY(字段名) REFERENCES 库.表名(字段名) ON UPDATE CASCADE ON DELETE CASCADE;