在当今数据驱动的时代,数据库作为数据存储与管理的核心工具,其重要性不言而喻。MySQL 作为一款广泛应用的开源数据库,凭借其高性能、高可靠性和丰富的功能,深受开发者喜爱。本文作为 MySQL 系列博客的开篇,将带你深入了解 MySQL 的基础概念、数据类型、完整性约束以及表间关系。
一、MySQL 介绍
1.1 关系型数据库概述
关系型数据库是基于关系模型建立的数据库,以行和列的形式存储数据,通过表格之间的关联来表达数据之间的关系。常见的关系型数据库有 SQL Server、Oracle、DB2、MariaDB 等。以安卓系统中的 SQLite 为例,它是一款进程内数据库,常用于移动端应用的本地数据存储,轻量级且易于集成。
与关系型数据库相对的是非关系型数据库,例如键值(k-v)存储的 Nosql、Redis,以及列式数据库 HBase 等。非关系型数据库在处理海量非结构化或半结构化数据时表现出色,而关系型数据库则在处理结构化数据、保证数据的一致性和完整性方面具有优势。
1.2 MySQL 的独特之处
MySQL 属于 Oracle 旗下的开源数据库,它区别于其他关系型数据库的一个很大特点是支持插件式存储引擎。这意味着开发者可以根据应用场景的不同,选择最适合的存储引擎。例如,InnoDB 引擎支持事务处理、外键约束,适合对数据完整性要求较高的应用;MyISAM 引擎则以其高性能的查询和插入操作,适用于只读或读多写少的场景。
MySQL 采用 C/S(客户端 / 服务器)模型,在架构设计上,使用 I/O 复用结合可伸缩线程池(select + 线程池)的方式。由于数据库操作涉及磁盘 I/O,在这种场景下,select 模型已经能够满足需求,没必要使用 epoll。这种架构设计使得 MySQL 能够高效地处理大量客户端请求,保证系统的稳定性和性能。
1.3 MySQL 的安装(ubuntu)
参考:【MySQL数据库】Ubuntu下的mysql_ubuntu mysql-CSDN博客
二、MySQL 数据类型
数据库操作中,磁盘 I/O 往往是最先遇到的性能瓶颈。MySQL 的数据类型定义了数据的大小范围,合理选择数据类型不仅能降低表占用的磁盘空间,还能减少磁盘 I/O 次数,提高访问效率。
2.1 整数类型
数据类型 |
字节 |
最小值(有符号) |
最大值(有符号) |
最小值(无符号) |
最大值(无符号) |
TINYINT |
1 |
-128 |
127 |
0 |
255 |
SMALLINT |
2 |
-32768 |
32767 |
0 |
65535 |
MEDIUMINT |
3 |
-8388608 |
8388607 |
0 |
16777215 |
INT |
4 |
-2147483648 |
2147483647 |
0 |
4294967295 |
BIGINT |
8 |
-9223372036854775808 |
9223372036854775807 |
0 |
18446744073709551615 |
在定义整数类型时,需要注意一些细节。例如:
CREATE TABLE users(
age INT(9) unsigned NOT NULL DEFAULT 0
);
这里INT(9)中的9是数据显示时的宽度,和字符类型不同,数值型数据大小和数据类型强相关,并不会因为括号内的数字而改变占用的内存空间。
2.2 字符串类型
数据类型 |
描述 |
最大长度 |
CHAR(M) |
固定长度字符串,M字节 |
255 个字符 |
VARCHAR(M) |
可变长度字符串 |
65535 个字符(受限于行的最大长度) |
TEXT |
文本字符串 |
65535 个字符 |
MEDIUMTEXT |
中等长度文本字符串 |
16777215 个字符 |
LONGTEXT |
长文本字符串 |
4294967295 个字符 |
假设我们要创建一个存储用户昵称的表:
CREATE TABLE users (
id INT AUTO_INCREMENT PRIMARY KEY,
username VARCHAR(50) NOT NULL
);
使用VARCHAR类型存储用户名,既能满足可变长度的需求,又能节省存储空间。
2.3 日期和时间类型
数据类型 |
描述 |
格式 |
DATE |
日期值 |
YYYY-MM-DD |
TIME |
时间值或持续时间 |
HH:MM:SS |
DATETIME |
日期和时间组合 |
YYYY-MM-DD HH:MM:SS |
TIMESTAMP |
时间戳 |
YYYY-MM-DD HH:MM:SS |
YEAR |
年份值 |
YYYY 或 YY |
例如,记录用户的注册时间:
CREATE TABLE user_registrations (
id INT AUTO_INCREMENT PRIMARY KEY,
registration_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
TIMESTAMP类型会自动记录插入数据时的时间,方便进行时间相关的统计和查询。
2.4 enum 和 set
ENUM类型用于定义一个字符串对象,该对象只能从预定义的列表中选取一个值;SET类型同样基于预定义的列表,但可以选取多个值。
CREATE TABLE products (
id INT AUTO_INCREMENT PRIMARY KEY,
size ENUM('S', 'M', 'L', 'XL'),
colors SET('red', 'green', 'blue')
);
在插入数据时,size字段只能是'S'、'M'、'L'、'XL'中的一个,而colors字段可以是'red'、'green'、'blue'的任意组合。
三、完整性约束
完整性约束用于确保数据库中数据的准确性和一致性,在 MySQL 中,常见的完整性约束有以下几种:
3.1 主键约束(PRIMARY KEY)
主键是表中的一列或多列组合,用于唯一标识表中的每一行记录。一个表只能有一个主键,且主键值不能为 NULL,也不能重复。例如,创建一个存储学生信息的表:
CREATE TABLE students (
student_id INT PRIMARY KEY,
student_name VARCHAR(50) NOT NULL,
age INT
);
这里student_id作为主键,能快速定位和区分每一位学生的记录。
3.2 自增键约束(AUTO_INCREMENT)
自增键是一种特殊的主键,通常为整数类型,在插入新记录时,其值会自动递增。一般用于生成唯一的标识。如:
CREATE TABLE orders (
order_id INT AUTO_INCREMENT PRIMARY KEY,
order_date DATE,
customer_id INT
);
每次向orders表插入新订单时,order_id都会自动生成一个唯一的递增数值。
3.3 唯一键约束(UNIQUE
)
唯一键约束保证表中指定列的值是唯一的,但可以有一个 NULL 值(如果允许 NULL)。例如,在用户表中,用户的邮箱地址应具有唯一性:
CREATE TABLE users (
user_id INT AUTO_INCREMENT PRIMARY KEY,
email VARCHAR(100) UNIQUE,
username VARCHAR(50) NOT NULL
);
这样能避免不同用户使用相同的邮箱进行注册。
3.4 非空约束(NOT NULL
)
非空约束规定列中不允许出现 NULL 值。在定义表结构时,若某列数据必须存在,就可以使用非空约束。如:
CREATE TABLE employees (
employee_id INT AUTO_INCREMENT PRIMARY KEY,
employee_name VARCHAR(50) NOT NULL,
department VARCHAR(50)
);
employee_name列必须有值,否则插入数据时会报错。
3.5 默认值约束(DEFAULT
)
默认值约束为列指定一个默认值,当插入数据时若未指定该列的值,就会使用默认值。例如,记录用户注册时间时,若不手动指定时间,就使用当前时间:
CREATE TABLE user_registrations (
id INT AUTO_INCREMENT PRIMARY KEY,
registration_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
user_id INT
);
3.6 外键约束
外键用于建立表与表之间的关联关系,确保数据的一致性和完整性。比如,有orders表和customers表,orders表中的customer_id需要关联到customers表的主键customer_id:
CREATE TABLE customers (
customer_id INT PRIMARY KEY,
customer_name VARCHAR(50) NOT NULL
);
CREATE TABLE orders (
order_id INT AUTO_INCREMENT PRIMARY KEY,
order_date DATE,
customer_id INT,
FOREIGN KEY (customer_id) REFERENCES customers(customer_id)
);
通过外键约束,能保证orders表中的customer_id在customers表中存在,避免出现无效的关联数据。
但是由于数据库需要进行磁盘I/O操作,导致数据库往往是性能瓶颈所在,因此业务中逻辑相关操作往往交给业务层代码实现,所以外键约束并不常用。(下文中外键约束仅用于理解表间关系)
四、表与表之间的关系
在设计数据库时,表与表之间的关系建模是关键环节,直接影响数据的存储效率、查询性能以及数据完整性。常见的表间关系包括一对一、一对多和多对多。
(1) 一对一
一对一关系是指两张表中的记录通过特定字段形成一一对应的映射,通常用于将一张表中部分不常用或敏感字段拆分到另一张表,以减少主表冗余或满足安全性需求。
案例:以电商系统中用户信息表和用户扩展信息表为例。用户表存储基础登录信息(如用户名、密码),扩展表存储用户详细资料(如身份证号、收货地址)。
-- 用户基础信息表
CREATE TABLE users (
user_id INT AUTO_INCREMENT PRIMARY KEY,
username VARCHAR(50) NOT NULL,
password VARCHAR(128) NOT NULL
);
-- 用户扩展信息表
CREATE TABLE user_extensions (
extension_id INT AUTO_INCREMENT PRIMARY KEY,
user_id INT UNIQUE, -- 通过user_id建立一对一关联
id_card VARCHAR(18),
shipping_address TEXT,
FOREIGN KEY (user_id) REFERENCES users(user_id)
);
关系实现:通过在user_extensions表中设置user_id字段作为外键,并添加UNIQUE约束,确保每个user_id仅对应一条扩展记录。当插入数据时,若user_extensions表中已存在某个user_id,则新记录插入失败,从而保证一对一关系的唯一性。
(2) 一对多
一对多关系是最常见的表间关系,指一张表(主表)的一条记录对应另一张表(从表)的多条记录。通常通过在从表中引入主表的主键作为外键实现关联。
案例:以学校管理系统中的班级表和学生表为例,一个班级包含多名学生。
-- 班级表(主表)
CREATE TABLE classes (
class_id INT AUTO_INCREMENT PRIMARY KEY,
class_name VARCHAR(20) NOT NULL,
teacher VARCHAR(50)
);
-- 学生表(从表)
CREATE TABLE students (
student_id INT AUTO_INCREMENT PRIMARY KEY,
student_name VARCHAR(50) NOT NULL,
age INT,
class_id INT, -- 引入班级表的主键作为外键
FOREIGN KEY (class_id) REFERENCES classes(class_id)
);
关系实现:在students表中通过class_id字段关联classes表的class_id主键。插入学生记录时,class_id必须是classes表中已存在的值,确保数据一致性。例如,查询某个班级的所有学生时,可通过JOIN操作:
SELECT s.student_name, c.class_name
FROM students s
JOIN classes c ON s.class_id = c.class_id
WHERE c.class_name = '高三(1)班';
(3)多对多
多对多关系表示两张表中的多条记录可相互关联,由于数据库无法直接存储这种关系,需引入中间表(也称关联表)进行建模。中间表包含两张主表的主键字段,通过组合主键确保关系的唯一性。
案例:以图书管理系统中的书籍表和读者表为例,一本书可被多名读者借阅,一个读者可借阅多本书。
-- 书籍表
CREATE TABLE books (
book_id INT AUTO_INCREMENT PRIMARY KEY,
book_title VARCHAR(100) NOT NULL,
author VARCHAR(50)
);
-- 读者表
CREATE TABLE readers (
reader_id INT AUTO_INCREMENT PRIMARY KEY,
reader_name VARCHAR(50) NOT NULL,
contact VARCHAR(100)
);
-- 中间表(借阅记录表)
CREATE TABLE borrow_records (
book_id INT,
reader_id INT,
borrow_date DATE,
return_date DATE,
PRIMARY KEY (book_id, reader_id), -- 组合主键确保唯一性
FOREIGN KEY (book_id) REFERENCES books(book_id),
FOREIGN KEY (reader_id) REFERENCES readers(reader_id)
);
中间表设计要点:
- 字段组成:包含关联的两张主表的主键字段(如book_id和reader_id),可按需添加其他属性(如借阅时间、归还时间)。
- 主键设置:使用组合主键(PRIMARY KEY (book_id, reader_id)),确保同一条书籍与读者的关联关系不会重复记录。
- 外键约束:通过外键关联主表主键,保证数据引用的完整性,例如删除书籍时,可通过外键级联操作同步删除相关借阅记录。
通过中间表,多对多关系被拆解为两个一对多关系,既保证数据的完整性,又能灵活实现复杂查询与业务逻辑。