程序员求职经验分享与学习资料整理平台

网站首页 > 文章精选 正文

SQL面试题及答案( Top20)(mysql面试题及答案)

balukai 2025-07-10 13:11:01 文章精选 4 ℃

概述

通过这些Top 20 SQL面试题及答案来破解您的SQL面试。包含详细解释、示例和关键差异,适用于应届生和有经验的候选人。


1. 什么是SQL?

答案:
SQL(结构化查询语言)是用于管理和操作数据库的标准语言。

示例:

SELECT * FROM employees;

2.DELETE、TRUNCATE和DROP之间有什么区别?

命令描述可回滚影响结构DELETE删除选定的行是否TRUNCATE快速删除所有行否否DROP删除整个表否是


3. SQL语句有哪些不同类型?

答案:

  • DDL – 数据定义语言(CREATEALTERDROP
  • DML – 数据操作语言(INSERTUPDATEDELETE
  • DQL – 数据查询语言(SELECT
  • DCL – 数据控制语言(GRANTREVOKE
  • TCL – 事务控制语言(COMMITROLLBACK

4. 什么是主键?

答案:
主键是唯一标识表中每一行的列(或列集合)。

示例:

CREATE TABLE students (
    student_id INT PRIMARY KEY,
    name VARCHAR(50)
);

5. 什么是外键?

答案:
外键是一个表中的列,指向另一个表中的主键,用于建立关系。

示例:

FOREIGN KEY (student_id) REFERENCES students(student_id)

6.WHERE和HAVING之间有什么区别?

子句用例作用于WHERE在分组前过滤行行HAVING在GROUP BY后过滤聚合数据

示例:

SELECT dept, COUNT(*) FROM employees
GROUP BY dept
HAVING COUNT(*) > 5;

7. SQL中的JOIN是什么?

答案:
JOIN用于组合两个或多个表中的行。

连接类型描述INNER JOIN匹配两个表中的行LEFT JOIN左表的所有行 + 右表的匹配行RIGHT JOIN右表的所有行 + 左表的匹配行FULL JOIN两个表中所有匹配 + 不匹配的行

示例:

SELECT e.name, d.name
FROM employees e
INNER JOIN departments d ON e.dept_id = d.id;

8.UNION和UNION ALL之间有什么区别?

关键字重复项更快UNION移除否UNION ALL保留是


9. 什么是规范化?

答案:
规范化是减少数据冗余和提高数据完整性的过程。

范式:

  • 1NF:原子列
  • 2NF:无部分依赖
  • 3NF:无传递依赖

10. 什么是子查询?

答案:
子查询是嵌套在另一个查询中的查询。

示例:

SELECT name FROM students
WHERE id IN (SELECT student_id FROM enrollments);

11.IN和EXISTS之间有什么区别?

  • IN:检查列表或子查询中的值。
  • EXISTS:检查子查询是否返回至少一行。

12. 什么是索引?

答案:
索引通过允许更快的搜索和检索来提高查询性能。

示例:

CREATE INDEX idx_name ON employees(name);

13. 什么是视图?

答案:
视图是基于SQL查询的虚拟表。

示例:

CREATE VIEW active_employees AS
SELECT * FROM employees WHERE status = 'active';

14. 什么是存储过程?

答案:
存储过程是预编译的SQL语句组。

示例:

CREATE PROCEDURE GetEmployees()
AS
BEGIN
    SELECT * FROM employees;
END;

15.CHAR和VARCHAR之间有什么区别?

类型固定/可变存储CHAR(n)固定长度始终n字节VARCHAR(n)可变长度最多n字节


16. SQL中的聚合函数有哪些?

答案:
聚合函数对多行执行计算。

函数用途SUM()求和AVG()平均值COUNT()计数行MAX()最大值MIN()最小值


17. 什么是约束?

答案:
约束对数据列强制执行规则。

  • NOT NULL
  • UNIQUE
  • PRIMARY KEY
  • FOREIGN KEY
  • CHECK
  • DEFAULT

18.BETWEEN和IN之间有什么区别?

  • BETWEEN检查范围。
  • IN检查特定值。

示例:

-- BETWEEN
SELECT * FROM students WHERE age BETWEEN 18 AND 25;

-- IN
SELECT * FROM students WHERE city IN ('Delhi', 'Mumbai');

19. SQL中的事务是什么?

答案:
事务是一个工作单元,要么完全完成,要么完全失败

命令:

  • BEGIN TRANSACTION
  • COMMIT
  • ROLLBACK

20. 如何优化慢SQL查询?

答案:

  • 使用索引
  • 避免SELECT *
  • 正确使用JOIN
  • 避免不必要的子查询
  • 使用EXPLAINQUERY PLAN分析

详细代码示例

数据库表结构示例

-- 创建学生表
CREATE TABLE students (
    student_id INT PRIMARY KEY AUTO_INCREMENT,
    name VARCHAR(100) NOT NULL,
    email VARCHAR(100) UNIQUE,
    age INT CHECK (age >= 0),
    department_id INT,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    FOREIGN KEY (department_id) REFERENCES departments(department_id)
);

-- 创建部门表
CREATE TABLE departments (
    department_id INT PRIMARY KEY AUTO_INCREMENT,
    name VARCHAR(50) NOT NULL,
    location VARCHAR(100)
);

-- 创建课程表
CREATE TABLE courses (
    course_id INT PRIMARY KEY AUTO_INCREMENT,
    name VARCHAR(100) NOT NULL,
    credits INT DEFAULT 3,
    instructor_id INT
);

-- 创建学生课程关联表
CREATE TABLE student_courses (
    student_id INT,
    course_id INT,
    grade DECIMAL(3,2),
    enrollment_date DATE,
    PRIMARY KEY (student_id, course_id),
    FOREIGN KEY (student_id) REFERENCES students(student_id),
    FOREIGN KEY (course_id) REFERENCES courses(course_id)
);

复杂查询示例

-- 1. 使用JOIN查询学生和部门信息
SELECT 
    s.name AS student_name,
    s.email,
    d.name AS department_name
FROM students s
LEFT JOIN departments d ON s.department_id = d.department_id
WHERE s.age BETWEEN 18 AND 25;

-- 2. 使用子查询查找平均分高于班级平均分的学生
SELECT 
    s.name,
    sc.grade
FROM students s
JOIN student_courses sc ON s.student_id = sc.student_id
WHERE sc.grade > (
    SELECT AVG(grade) 
    FROM student_courses 
    WHERE course_id = sc.course_id
);

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

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

-- 5. 使用CTE(公用表表达式)
WITH high_performers AS (
    SELECT student_id, AVG(grade) as avg_grade
    FROM student_courses
    GROUP BY student_id
    HAVING AVG(grade) >= 3.5
)
SELECT 
    s.name,
    hp.avg_grade
FROM students s
JOIN high_performers hp ON s.student_id = hp.student_id;

存储过程和函数示例

-- 创建存储过程
DELIMITER //
CREATE PROCEDURE GetStudentInfo(IN student_id_param INT)
BEGIN
    SELECT 
        s.name,
        s.email,
        d.name AS department,
        COUNT(sc.course_id) AS enrolled_courses,
        AVG(sc.grade) AS average_grade
    FROM students s
    LEFT JOIN departments d ON s.department_id = d.department_id
    LEFT JOIN student_courses sc ON s.student_id = sc.student_id
    WHERE s.student_id = student_id_param
    GROUP BY s.student_id, s.name, s.email, d.name;
END //
DELIMITER ;

-- 创建函数
DELIMITER //
CREATE FUNCTION GetStudentGrade(student_id_param INT, course_id_param INT)
RETURNS DECIMAL(3,2)
READS SQL DATA
DETERMINISTIC
BEGIN
    DECLARE student_grade DECIMAL(3,2);
    
    SELECT grade INTO student_grade
    FROM student_courses
    WHERE student_id = student_id_param 
    AND course_id = course_id_param;
    
    RETURN COALESCE(student_grade, 0.00);
END //
DELIMITER ;

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

-- 使用函数
SELECT GetStudentGrade(1, 101) AS grade;

索引和性能优化示例

-- 创建复合索引
CREATE INDEX idx_student_dept_age ON students(department_id, age);

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

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

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

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

-- 优化的查询
SELECT student_id, name, email FROM students 
WHERE name LIKE 'John%' 
LIMIT 10;

事务处理示例

-- 开始事务
START TRANSACTION;

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

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

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

-- 提交事务
COMMIT;

-- 错误处理示例
START TRANSACTION;
BEGIN
    DECLARE EXIT HANDLER FOR SQLEXCEPTION
    BEGIN
        ROLLBACK;
        SELECT 'Transaction failed' AS message;
    END;
    
    INSERT INTO students (name, email, age, department_id) 
    VALUES ('李四', 'lisi@example.com', 22, 1);
    
    INSERT INTO student_courses (student_id, course_id, grade, enrollment_date)
    VALUES (LAST_INSERT_ID(), 101, NULL, CURDATE());
    
    COMMIT;
    SELECT 'Transaction successful' AS message;
END;

面试技巧

1. 准备阶段

  • 复习基本的SQL语法和概念
  • 练习编写复杂查询
  • 理解数据库设计原则
  • 熟悉性能优化技巧

2. 面试中

  • 仔细阅读问题要求
  • 先思考再编码
  • 解释你的思路
  • 考虑边界情况
  • 讨论性能影响

3. 常见陷阱

  • 忘记处理NULL值
  • 忽略索引的重要性
  • 不熟悉事务处理
  • 缺乏对数据类型的理解

总结

这20个SQL面试题涵盖了从基础概念到高级特性的各个方面:

  1. 基础概念:SQL语法、数据类型、约束
  2. 查询操作:SELECT、JOIN、子查询、聚合函数
  3. 数据操作:INSERT、UPDATE、DELETE、事务
  4. 性能优化:索引、查询优化、存储过程
  5. 数据库设计:规范化、主键、外键

掌握这些概念将帮助您在SQL面试中表现出色,并在实际工作中编写高效、可维护的数据库代码。

最近发表
标签列表