SQL综合实战:从基础约束到高级应用的完整指南

引言

在数据库管理和应用开发中,SQL是不可或缺的核心技能。无论是简单的数据查询还是复杂的业务逻辑处理,都需要扎实的SQL功底。本文通过两个综合性的SQL练习题,带你系统学习SQL的各项重要功能。

第一题:数据库基础操作全解析

1.1 数据表创建与约束管理

需求分析:创建学生表,要求包含学号、姓名、性别、年龄、所在系字段,并设置相应的约束条件。

复制代码
-- 创建学生表,包含多种约束类型
CREATE TABLE Student (
    Sno VARCHAR(20) PRIMARY KEY,           -- 学号,主键
    Sname VARCHAR(50) UNIQUE NOT NULL,     -- 姓名,唯一且非空
    Ssex ENUM('男', '女') NOT NULL,        -- 性别,枚举约束
    Sage INT NOT NULL,                              -- 年龄
    Sdept VARCHAR(50) DEFAULT '计算机'     -- 所在系,默认值
);

技术要点解析

  • 主键约束 (PRIMARY KEY):确保学号的唯一性,每个学生有唯一标识

  • 唯一约束 (UNIQUE):防止姓名重复,保证数据唯一性

  • 枚举约束 (ENUM):限制性别只能输入'男'或'女',保证数据规范性

  • 默认值 (DEFAULT):简化数据插入,提高开发效率

1.2 表结构修改技巧

业务场景:随着系统演进,需要调整字段数据类型以优化存储空间。

复制代码
-- 修改年龄字段的数据类型
ALTER TABLE Student MODIFY Sage SMALLINT;

优化效果

  • INT 类型占用4字节,存储范围:-2,147,483,648 到 2,147,483,647

  • SMALLINT 类型占用2字节,存储范围:-32,768 到 32,768

  • 对于年龄字段,使用SMALLINT完全足够且节省存储空间

1.3 索引设计与性能优化

业务需求:为选课表创建复合主键索引,提升查询性能。

复制代码
-- 创建复合主键索引
CREATE UNIQUE INDEX SC_INDEX ON SC (Sno, Cno);

索引设计原则

  1. 复合索引顺序:先学号后课程号,符合查询模式

  2. 唯一性保证:防止同一学生重复选同一门课程

  3. 查询优化:加速基于学号和课程号的联合查询

应用场景

复制代码
-- 以下查询将利用索引
SELECT * FROM SC WHERE Sno = '2023001';
SELECT * FROM SC WHERE Sno = '2023001' AND Cno = 'C001';

1.4 视图创建与数据抽象

业务需求:创建视图方便查询学生选课信息。

复制代码
-- 创建学生选课信息视图
CREATE VIEW stu_info AS
SELECT s.Sname, s.Ssex, c.Cname, sc.Score
FROM Student s
JOIN SC sc ON s.Sno = sc.Sno
JOIN Course c ON sc.Cno = c.Cno;

视图的优势

  • 简化复杂查询:隐藏多表连接的复杂性

  • 数据安全性:只暴露必要的字段信息

  • 逻辑独立性:底层表结构变化不影响上层应用

使用示例

复制代码
-- 简单查询所有学生选课信息
SELECT * FROM stu_info;

-- 查询特定性别的学生选课情况
SELECT * FROM stu_info WHERE Ssex = '男';

第二题:存储过程与业务逻辑封装

2.1 部门平均工资统计存储过程

业务需求:创建存储过程统计指定部门的平均工资。

复制代码
DELIMITER //

CREATE PROCEDURE avg_sal_a(
    IN dept_name VARCHAR(50),      -- 输入参数:部门名称
    OUT avg_salary DECIMAL(10,2)   -- 输出参数:平均工资
)
BEGIN
    -- 计算指定部门的平均工资
    SELECT AVG(salary) INTO avg_salary 
    FROM Employee 
    WHERE department = dept_name;
END//

DELIMITER ;

技术特点

  • 参数传递:使用IN参数接收输入,OUT参数返回结果

  • 业务逻辑封装:将复杂计算逻辑封装在数据库中

  • 代码复用:多个应用可以调用同一存储过程

调用示例

复制代码
-- 调用存储过程并获取结果
CALL avg_sal_a('上海中心', @a);
SELECT @a AS 上海中心平均工资;

2.2 部门最高工资查询存储过程

业务需求:根据员工姓名查询其所在部门的最高工资。

复制代码
DELIMITER //

CREATE PROCEDURE get_dept_max_salary(
    IN emp_name VARCHAR(50),       -- 输入参数:员工姓名
    OUT max_salary DECIMAL(10,2)   -- 输出参数:部门最高工资
)
BEGIN
    -- 子查询获取员工部门,再查询该部门最高工资
    SELECT MAX(e.salary) INTO max_salary
    FROM Employee e
    WHERE e.department = (
        SELECT department 
        FROM Employee 
        WHERE name = emp_name
    );
END//

DELIMITER ;

设计思路

  1. 子查询应用:先通过员工姓名查询所在部门

  2. 聚合函数:使用MAX函数计算部门最高工资

  3. 结果返回:通过OUT参数返回计算结果

调用测试

复制代码
-- 测试存储过程功能
CALL get_dept_max_salary('张三', @a);
SELECT @a AS 部门最高工资;

实战技巧与最佳实践

3.1 约束设计的思考

为什么需要约束?

  1. 数据完整性:防止无效数据进入系统

  2. 业务规则:在数据库层面保证业务规则执行

  3. 应用简化:减少应用层的校验逻辑

3.2 索引使用建议

创建索引的时机

  • 频繁作为查询条件的字段

  • 经常需要排序的字段

  • 表数据量较大时

避免过度索引

  • 索引会占用存储空间

  • 影响数据插入、更新、删除性能

3.3 存储过程的优势

性能提升

  • 减少网络传输

  • 预编译执行计划

维护便利

  • 业务逻辑集中管理

  • 修改时不影响应用代码

相关推荐
ohoy1 小时前
mysql 30天自动补0
数据库·mysql
Hello.Reader2 小时前
Flink SQL DELETE 语句批模式行级删除、连接器能力要求与实战避坑(含 Java 示例)
java·sql·flink
摇滚侠3 小时前
Redis 零基础到进阶,Redis 哨兵监控,笔记63-73
数据库·redis·笔记
利剑 -~4 小时前
mysql面试题整理
android·数据库·mysql
老华带你飞4 小时前
物流信息管理|基于springboot 物流信息管理系统(源码+数据库+文档)
数据库·vue.js·spring boot
程序员卷卷狗4 小时前
Redis事务与MySQL事务有什么区别?一文分清
数据库·redis·mysql
玩大数据的龙威4 小时前
农经权二轮延包—数据(新老农经权)比对软件更新
数据库·arcgis
保持低旋律节奏4 小时前
网络系统管理——期末复习
数据库
程序员佳佳5 小时前
2025年大模型终极横评:GPT-5.2、Banana Pro与DeepSeek V3.2实战硬核比拼(附统一接入方案)
服务器·数据库·人工智能·python·gpt·api
roo_15 小时前
github 获取构造图数据库的LNB数据集和使用说明
数据库