Top 20 SQL面试题及答案

概述
通过这些Top 20 SQL面试题及答案来破解您的SQL面试。包含详细解释、示例和关键差异,适用于应届生和有经验的候选人。
🔹 1. 什么是SQL?
答案:
SQL(结构化查询语言)是用于管理和操作数据库的标准语言。
示例:
  1. SELECT * FROM employees;
sql
🔹 2. DELETETRUNCATEDROP之间有什么区别?
命令
描述
可回滚
影响结构
DELETE
删除选定的行
TRUNCATE
快速删除所有行
DROP
删除整个表
🔹 3. SQL语句有哪些不同类型?
答案:
DDL 数据定义语言(CREATEALTERDROP
DML 数据操作语言(INSERTUPDATEDELETE
DQL 数据查询语言(SELECT
DCL 数据控制语言(GRANTREVOKE
TCL 事务控制语言(COMMITROLLBACK
🔹 4. 什么是主键?
答案:
主键是唯一标识表中每一行的列(或列集合)。
示例:
  1. CREATE TABLE students (
  2. student_id INT PRIMARY KEY,
  3. name VARCHAR(50)
  4. );
sql
🔹 5. 什么是外键?
答案:
外键是一个表中的列,指向另一个表中的主键,用于建立关系。
示例:
  1. FOREIGN KEY (student_id) REFERENCES students(student_id)
sql
🔹 6. WHEREHAVING之间有什么区别?
子句
用例
作用于
WHERE
在分组前过滤行
HAVING
在GROUP BY后过滤
聚合数据
示例:
  1. SELECT dept, COUNT(*) FROM employees
  2. GROUP BY dept
  3. HAVING COUNT(*) > 5;
sql
🔹 7. SQL中的JOIN是什么?
答案:
JOIN用于组合两个或多个表中的行。
连接类型
描述
INNER JOIN
匹配两个表中的行
LEFT JOIN
左表的所有行 + 右表的匹配行
RIGHT JOIN
右表的所有行 + 左表的匹配行
FULL JOIN
两个表中所有匹配 + 不匹配的行
示例:
  1. SELECT e.name, d.name
  2. FROM employees e
  3. INNER JOIN departments d ON e.dept_id = d.id;
sql
🔹 8. UNIONUNION ALL之间有什么区别?
关键字
重复项
更快
UNION
移除
UNION ALL
保留
🔹 9. 什么是规范化?
答案:
规范化是减少数据冗余和提高数据完整性的过程。
范式:
1NF:原子列
2NF:无部分依赖
3NF:无传递依赖
🔹 10. 什么是子查询?
答案:
子查询是嵌套在另一个查询中的查询。
示例:
  1. SELECT name FROM students
  2. WHERE id IN (SELECT student_id FROM enrollments);
sql
🔹 11. INEXISTS之间有什么区别?
IN:检查列表或子查询中的值。
EXISTS:检查子查询是否返回至少一行。
🔹 12. 什么是索引?
答案:
索引通过允许更快的搜索和检索来提高查询性能。
示例:
  1. CREATE INDEX idx_name ON employees(name);
sql
🔹 13. 什么是视图?
答案:
视图是基于SQL查询的虚拟表。
示例:
  1. CREATE VIEW active_employees AS
  2. SELECT * FROM employees WHERE status = 'active';
sql
🔹 14. 什么是存储过程?
答案:
存储过程是预编译的SQL语句组。
示例:
  1. CREATE PROCEDURE GetEmployees()
  2. AS
  3. BEGIN
  4. SELECT * FROM employees;
  5. END;
sql
🔹 15. CHARVARCHAR之间有什么区别?
类型
固定/可变
存储
CHAR(n)
固定长度
始终n字节
VARCHAR(n)
可变长度
最多n字节
🔹 16. SQL中的聚合函数有哪些?
答案:
聚合函数对多行执行计算。
函数
用途
SUM()
求和
AVG()
平均值
COUNT()
计数行
MAX()
最大值
MIN()
最小值
🔹 17. 什么是约束?
答案:
约束对数据列强制执行规则。
NOT NULL
UNIQUE
PRIMARY KEY
FOREIGN KEY
CHECK
DEFAULT
🔹 18. BETWEENIN之间有什么区别?
BETWEEN检查范围。
IN检查特定值。
示例:
  1. -- BETWEEN
  2. SELECT * FROM students WHERE age BETWEEN 18 AND 25;

  3. -- IN
  4. SELECT * FROM students WHERE city IN ('Delhi', 'Mumbai');
sql
🔹 19. SQL中的事务是什么?
答案:
事务是一个工作单元,要么完全完成,要么完全失败
命令:
BEGIN TRANSACTION
COMMIT
ROLLBACK
🔹 20. 如何优化慢SQL查询?
答案:
使用索引
避免SELECT
正确使用JOIN
避免不必要的子查询
使用EXPLAINQUERY PLAN分析
详细代码示例
数据库表结构示例
  1. -- 创建学生表
  2. CREATE TABLE students (
  3. student_id INT PRIMARY KEY AUTO_INCREMENT,
  4. name VARCHAR(100) NOT NULL,
  5. email VARCHAR(100) UNIQUE,
  6. age INT CHECK (age >= 0),
  7. department_id INT,
  8. created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  9. FOREIGN KEY (department_id) REFERENCES departments(department_id)
  10. );

  11. -- 创建部门表
  12. CREATE TABLE departments (
  13. department_id INT PRIMARY KEY AUTO_INCREMENT,
  14. name VARCHAR(50) NOT NULL,
  15. location VARCHAR(100)
  16. );

  17. -- 创建课程表
  18. CREATE TABLE courses (
  19. course_id INT PRIMARY KEY AUTO_INCREMENT,
  20. name VARCHAR(100) NOT NULL,
  21. credits INT DEFAULT 3,
  22. instructor_id INT
  23. );

  24. -- 创建学生课程关联表
  25. CREATE TABLE student_courses (
  26. student_id INT,
  27. course_id INT,
  28. grade DECIMAL(3,2),
  29. enrollment_date DATE,
  30. PRIMARY KEY (student_id, course_id),
  31. FOREIGN KEY (student_id) REFERENCES students(student_id),
  32. FOREIGN KEY (course_id) REFERENCES courses(course_id)
  33. );
sql
复杂查询示例
  1. -- 1. 使用JOIN查询学生和部门信息
  2. SELECT
  3. s.name AS student_name,
  4. s.email,
  5. d.name AS department_name
  6. FROM students s
  7. LEFT JOIN departments d ON s.department_id = d.department_id
  8. WHERE s.age BETWEEN 18 AND 25;

  9. -- 2. 使用子查询查找平均分高于班级平均分的学生
  10. SELECT
  11. s.name,
  12. sc.grade
  13. FROM students s
  14. JOIN student_courses sc ON s.student_id = sc.student_id
  15. WHERE sc.grade > (
  16. SELECT AVG(grade)
  17. FROM student_courses
  18. WHERE course_id = sc.course_id
  19. );

  20. -- 3. 使用聚合函数和GROUP BY
  21. SELECT
  22. d.name AS department,
  23. COUNT(s.student_id) AS student_count,
  24. AVG(s.age) AS avg_age
  25. FROM departments d
  26. LEFT JOIN students s ON d.department_id = s.department_id
  27. GROUP BY d.department_id, d.name
  28. HAVING COUNT(s.student_id) > 5;

  29. -- 4. 使用窗口函数
  30. SELECT
  31. s.name,
  32. sc.grade,
  33. RANK() OVER (PARTITION BY sc.course_id ORDER BY sc.grade DESC) AS rank_in_course
  34. FROM students s
  35. JOIN student_courses sc ON s.student_id = sc.student_id;

  36. -- 5. 使用CTE(公用表表达式)
  37. WITH high_performers AS (
  38. SELECT student_id, AVG(grade) as avg_grade
  39. FROM student_courses
  40. GROUP BY student_id
  41. HAVING AVG(grade) >= 3.5
  42. )
  43. SELECT
  44. s.name,
  45. hp.avg_grade
  46. FROM students s
  47. JOIN high_performers hp ON s.student_id = hp.student_id;
sql
存储过程和函数示例
  1. -- 创建存储过程
  2. DELIMITER //
  3. CREATE PROCEDURE GetStudentInfo(IN student_id_param INT)
  4. BEGIN
  5. SELECT
  6. s.name,
  7. s.email,
  8. d.name AS department,
  9. COUNT(sc.course_id) AS enrolled_courses,
  10. AVG(sc.grade) AS average_grade
  11. FROM students s
  12. LEFT JOIN departments d ON s.department_id = d.department_id
  13. LEFT JOIN student_courses sc ON s.student_id = sc.student_id
  14. WHERE s.student_id = student_id_param
  15. GROUP BY s.student_id, s.name, s.email, d.name;
  16. END //
  17. DELIMITER ;

  18. -- 创建函数
  19. DELIMITER //
  20. CREATE FUNCTION GetStudentGrade(student_id_param INT, course_id_param INT)
  21. RETURNS DECIMAL(3,2)
  22. READS SQL DATA
  23. DETERMINISTIC
  24. BEGIN
  25. DECLARE student_grade DECIMAL(3,2);
  26. SELECT grade INTO student_grade
  27. FROM student_courses
  28. WHERE student_id = student_id_param
  29. AND course_id = course_id_param;
  30. RETURN COALESCE(student_grade, 0.00);
  31. END //
  32. DELIMITER ;

  33. -- 使用存储过程
  34. CALL GetStudentInfo(1);

  35. -- 使用函数
  36. SELECT GetStudentGrade(1, 101) AS grade;
sql
索引和性能优化示例
  1. -- 创建复合索引
  2. CREATE INDEX idx_student_dept_age ON students(department_id, age);

  3. -- 创建部分索引(MySQL 8.0+)
  4. CREATE INDEX idx_active_students ON students(name) WHERE age >= 18;

  5. -- 分析查询性能
  6. EXPLAIN SELECT * FROM students WHERE department_id = 1 AND age > 20;

  7. -- 查看索引使用情况
  8. SHOW INDEX FROM students;

  9. -- 优化查询示例
  10. -- 不好的查询
  11. SELECT * FROM students WHERE name LIKE '%John%';

  12. -- 优化的查询
  13. SELECT student_id, name, email FROM students
  14. WHERE name LIKE 'John%'
  15. LIMIT 10;
sql
事务处理示例
  1. -- 开始事务
  2. START TRANSACTION;

  3. -- 插入新学生
  4. INSERT INTO students (name, email, age, department_id)
  5. VALUES ('张三', 'zhangsan@example.com', 20, 1);

  6. -- 获取新插入的学生ID
  7. SET @new_student_id = LAST_INSERT_ID();

  8. -- 为学生注册课程
  9. INSERT INTO student_courses (student_id, course_id, grade, enrollment_date)
  10. VALUES (@new_student_id, 101, NULL, CURDATE());

  11. -- 提交事务
  12. COMMIT;

  13. -- 错误处理示例
  14. START TRANSACTION;
  15. BEGIN
  16. DECLARE EXIT HANDLER FOR SQLEXCEPTION
  17. BEGIN
  18. ROLLBACK;
  19. SELECT 'Transaction failed' AS message;
  20. END;
  21. INSERT INTO students (name, email, age, department_id)
  22. VALUES ('李四', 'lisi@example.com', 22, 1);
  23. INSERT INTO student_courses (student_id, course_id, grade, enrollment_date)
  24. VALUES (LAST_INSERT_ID(), 101, NULL, CURDATE());
  25. COMMIT;
  26. SELECT 'Transaction successful' AS message;
  27. END;
sql
面试技巧
1. 准备阶段
复习基本的SQL语法和概念
练习编写复杂查询
理解数据库设计原则
熟悉性能优化技巧
2. 面试中
仔细阅读问题要求
先思考再编码
解释你的思路
考虑边界情况
讨论性能影响
3. 常见陷阱
忘记处理NULL值
忽略索引的重要性
不熟悉事务处理
缺乏对数据类型的理解
总结
这20个SQL面试题涵盖了从基础概念到高级特性的各个方面:
基础概念:SQL语法、数据类型、约束
查询操作:SELECT、JOIN、子查询、聚合函数
数据操作:INSERT、UPDATE、DELETE、事务
性能优化:索引、查询优化、存储过程
数据库设计:规范化、主键、外键
掌握这些概念将帮助您在SQL面试中表现出色,并在实际工作中编写高效、可维护的数据库代码。