MySQL高级特性全面解析:约束、表关系、多表查询与事务
MySQL高级特性全面解析:约束、表关系、多表查询与事务
一、约束:数据完整性的守护者
1.1 约束概述
约束是作用于表中列的规则,用于限制加入表的数据,保证数据的:
- 正确性:如年龄不能为负数
- 有效性:如成绩范围合理
- 完整性:如部门与员工的关联关系
1.2 约束分类与语法
非空约束(NOT NULL)
-- 创建表时添加
CREATE TABLE users (id INT NOT NULL,username VARCHAR(50) NOT NULL
);-- 建表后添加
ALTER TABLE users MODIFY email VARCHAR(100) NOT NULL;
唯一约束(UNIQUE)
-- 创建表时添加
CREATE TABLE products (product_code VARCHAR(20) UNIQUE
);-- 建表后添加唯一约束
ALTER TABLE employees ADD UNIQUE (employee_id);
主键约束(PRIMARY KEY)
-- 创建表时添加(带自增长)
CREATE TABLE orders (order_id INT PRIMARY KEY AUTO_INCREMENT
);-- 建表后添加主键
ALTER TABLE customers ADD PRIMARY KEY (customer_id);
默认约束(DEFAULT)
-- 创建表时设置默认值
CREATE TABLE employees (status TINYINT DEFAULT 1,join_date DATE DEFAULT CURRENT_DATE
);-- 修改默认值
ALTER TABLE orders ALTER COLUMN status SET DEFAULT 0;
外键约束(FOREIGN KEY)
-- 创建表时添加外键
CREATE TABLE orders (customer_id INT,FOREIGN KEY (customer_id) REFERENCES customers(id)
);-- 建表后添加外键
ALTER TABLE order_items
ADD CONSTRAINT fk_order_id
FOREIGN KEY (order_id) REFERENCES orders(id);
1.3 约束实战案例
CREATE TABLE employees (id INT PRIMARY KEY AUTO_INCREMENT,name VARCHAR(50) NOT NULL UNIQUE,email VARCHAR(100) UNIQUE,dept_id INT NOT NULL,salary DECIMAL(10,2) DEFAULT 0.00,CONSTRAINT fk_dept FOREIGN KEY (dept_id) REFERENCES departments(id)
);
二、数据库设计:表关系与实现
2.1 表关系类型
一对多(1:N)
- 场景:部门与员工、分类与商品
- 实现:在多的一方添加外键指向一的一方主键
CREATE TABLE departments (id INT PRIMARY KEY AUTO_INCREMENT,name VARCHAR(50)
);CREATE TABLE employees (id INT PRIMARY KEY AUTO_INCREMENT,name VARCHAR(50),dept_id INT,FOREIGN KEY (dept_id) REFERENCES departments(id)
);
多对多(M:N)
- 场景:学生与课程、订单与商品
- 实现:创建中间表,包含两个外键
CREATE TABLE students (id INT PRIMARY KEY AUTO_INCREMENT,name VARCHAR(50)
);CREATE TABLE courses (id INT PRIMARY KEY AUTO_INCREMENT,title VARCHAR(100)
);CREATE TABLE student_courses (student_id INT,course_id INT,PRIMARY KEY (student_id, course_id),FOREIGN KEY (student_id) REFERENCES students(id),FOREIGN KEY (course_id) REFERENCES courses(id)
);
一对一(1:1)
- 场景:用户与用户详情、员工与社保信息
- 实现:在任意一方添加唯一外键
CREATE TABLE users (id INT PRIMARY KEY AUTO_INCREMENT,username VARCHAR(50) UNIQUE
);CREATE TABLE user_details (user_id INT PRIMARY KEY,address VARCHAR(200),phone VARCHAR(20),FOREIGN KEY (user_id) REFERENCES users(id)
);
2.2 数据库设计实战
在线音乐平台数据库设计:
-- 专辑表
CREATE TABLE albums (id INT PRIMARY KEY AUTO_INCREMENT,title VARCHAR(100) NOT NULL,artist VARCHAR(50) NOT NULL
);-- 曲目表
CREATE TABLE tracks (id INT PRIMARY KEY AUTO_INCREMENT,title VARCHAR(100) NOT NULL,duration INT NOT NULL,album_id INT NOT NULL,FOREIGN KEY (album_id) REFERENCES albums(id)
);-- 用户表
CREATE TABLE users (id INT PRIMARY KEY AUTO_INCREMENT,username VARCHAR(50) UNIQUE NOT NULL
);-- 专辑评论中间表
CREATE TABLE album_comments (album_id INT,user_id INT,comment TEXT,created_at DATETIME DEFAULT CURRENT_TIMESTAMP,PRIMARY KEY (album_id, user_id),FOREIGN KEY (album_id) REFERENCES albums(id),FOREIGN KEY (user_id) REFERENCES users(id)
);
三、多表查询:复杂数据检索
3.1 连接查询
内连接(INNER JOIN)
-- 显式内连接
SELECT e.name, d.department_name
FROM employees e
INNER JOIN departments d ON e.dept_id = d.id;-- 隐式内连接
SELECT e.name, d.department_name
FROM employees e, departments d
WHERE e.dept_id = d.id;
外连接(OUTER JOIN)
-- 左外连接(包含左表所有记录)
SELECT d.department_name, COUNT(e.id) AS employee_count
FROM departments d
LEFT JOIN employees e ON d.id = e.dept_id
GROUP BY d.id;-- 右外连接(包含右表所有记录)
SELECT c.customer_name, o.order_date
FROM customers c
RIGHT JOIN orders o ON c.id = o.customer_id;
3.2 子查询:查询嵌套
单行子查询
-- 查询比平均工资高的员工
SELECT name, salary
FROM employees
WHERE salary > (SELECT AVG(salary) FROM employees);
多行子查询
-- 查询研发部所有员工
SELECT name
FROM employees
WHERE dept_id IN (SELECT id FROM departments WHERE name = '研发部'
);
关联子查询
-- 查询每个部门工资最高的员工
SELECT e1.name, e1.salary, e1.dept_id
FROM employees e1
WHERE e1.salary = (SELECT MAX(salary)FROM employees e2WHERE e2.dept_id = e1.dept_id
);
3.3 综合查询案例
-- 查询员工信息及所在部门名称
SELECT e.id, e.name, e.salary, d.department_name AS dept,j.job_title
FROM employees e
JOIN departments d ON e.dept_id = d.id
JOIN jobs j ON e.job_id = j.id
WHERE e.salary > 10000
ORDER BY e.salary DESC;-- 查询部门及其员工数量
SELECT d.department_name,(SELECT COUNT(*) FROM employees e WHERE e.dept_id = d.id) AS employee_count
FROM departments d;
四、事务:数据操作的原子性保障
4.1 事务概念
事务是数据库操作的逻辑单元,具有ACID特性:
- 原子性(Atomicity):操作要么全部成功,要么全部失败
- 一致性(Consistency):事务前后数据状态一致
- 隔离性(Isolation):并发事务相互隔离
- 持久性(Durability):事务提交后结果永久保存
4.2 事务操作语法
-- 开启事务
START TRANSACTION;-- 执行操作
UPDATE accounts SET balance = balance - 500 WHERE id = 1;
UPDATE accounts SET balance = balance + 500 WHERE id = 2;-- 根据执行结果提交或回滚
COMMIT; -- 成功提交
-- ROLLBACK; -- 失败回滚
4.3 事务实战:银行转账
-- 创建账户表
CREATE TABLE accounts (id INT PRIMARY KEY AUTO_INCREMENT,name VARCHAR(50) NOT NULL,balance DECIMAL(10,2) NOT NULL
);-- 转账事务
START TRANSACTION;-- 从A账户扣款
UPDATE accounts SET balance = balance - 1000 WHERE id = 1;-- 模拟系统故障
-- 此处故意引发错误-- 向B账户存款
UPDATE accounts SET balance = balance + 1000 WHERE id = 2;-- 根据执行结果决定提交或回滚
IF NO_ERROR THENCOMMIT;SELECT '转账成功' AS result;
ELSEROLLBACK;SELECT '转账失败,已回滚' AS result;
END IF;
4.4 事务隔离级别
MySQL支持四种隔离级别:
- READ UNCOMMITTED:可能读取未提交数据(脏读)
- READ COMMITTED:避免脏读,可能不可重复读
- REPEATABLE READ(默认):避免脏读和不可重复读
- SERIALIZABLE:完全串行化执行,避免所有并发问题
查看和设置隔离级别:
-- 查看当前隔离级别
SELECT @@transaction_isolation;-- 设置隔离级别
SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
五、高级特性最佳实践
-
约束使用原则
- 主键选择:自增整数或业务无关唯一值
- 外键命名:fk_从表_主表
- 慎用级联:ON DELETE CASCADE可能引发连锁反应
-
表关系设计技巧
- 一对多:最常见的关系类型
- 多对多:使用中间表降低复杂度
- 一对一:垂直分表提升查询效率
-
多表查询优化
- 避免SELECT *:只选择必要字段
- 使用表别名:简化复杂查询
- 合理使用索引:外键字段必须索引
-
事务设计建议
- 保持事务简短:减少锁竞争时间
- 避免事务嵌套:MySQL不支持嵌套事务
- 处理死锁:设置合理的锁等待超时
-- 事务最佳实践示例
START TRANSACTION;-- 1. 记录操作日志
INSERT INTO operation_log (user_id, action) VALUES (123, '转账操作');-- 2. 执行核心业务
UPDATE accounts SET balance = balance - 500 WHERE id = 1;
UPDATE accounts SET balance = balance + 500 WHERE id = 2;-- 3. 提交事务
COMMIT;
总结
MySQL高级特性是构建健壮、高效数据库系统的关键。约束机制保障了数据的完整性和一致性,合理的表关系设计是高效查询的基础,多表查询技术实现了复杂数据的灵活检索,而事务管理确保了关键操作的原子性和安全性。掌握这些高级特性,结合最佳实践,能够显著提升数据库应用的性能和可靠性,为复杂业务场景提供坚实的数据支撑。在实际应用中,应根据具体需求选择合适的特性和配置,平衡性能与数据安全的关系。