Skip to content

SQL基础面试题

1. SQL的基本概念

问题:什么是SQL?SQL有哪些分类?

答案

  • SQL(Structured Query Language):结构化查询语言,用于管理关系型数据库。
  • 分类
    • DDL(Data Definition Language):数据定义语言,如CREATE、ALTER、DROP。
    • DML(Data Manipulation Language):数据操作语言,如INSERT、UPDATE、DELETE。
    • DQL(Data Query Language):数据查询语言,如SELECT。
    • DCL(Data Control Language):数据控制语言,如GRANT、REVOKE。
    • TCL(Transaction Control Language):事务控制语言,如COMMIT、ROLLBACK。

2. SELECT语句

问题:SELECT语句的基本语法是什么?

答案

sql
SELECT column1, column2, ...
FROM table_name
WHERE condition
GROUP BY column1, column2, ...
HAVING condition
ORDER BY column1, column2, ...
LIMIT offset, count;

3. WHERE子句

问题:WHERE子句中常用的运算符有哪些?

答案

  • 比较运算符:=、!=、<>、>、<、>=、<=
  • 逻辑运算符:AND、OR、NOT
  • 范围运算符:BETWEEN、IN、NOT IN
  • 模糊匹配:LIKE、NOT LIKE
  • 空值判断:IS NULL、IS NOT NULL

4. LIKE运算符

问题:LIKE运算符中常用的通配符有哪些?

答案

  • %:匹配任意多个字符。
  • _:匹配单个字符。

示例

sql
-- 查询名字以J开头的用户
SELECT * FROM users WHERE name LIKE 'J%';

-- 查询名字包含oh的用户
SELECT * FROM users WHERE name LIKE '%oh%';

-- 查询名字第二个字符为o的用户
SELECT * FROM users WHERE name LIKE '_o%';

5. GROUP BY和HAVING

问题:GROUP BY和HAVING有什么区别?

答案

  • GROUP BY:根据一个或多个列对结果集进行分组。
  • HAVING:对分组后的结果集进行过滤。

示例

sql
-- 查询每个部门的平均工资
SELECT department, AVG(salary) AS avg_salary
FROM employees
GROUP BY department;

-- 查询平均工资大于5000的部门
SELECT department, AVG(salary) AS avg_salary
FROM employees
GROUP BY department
HAVING AVG(salary) > 5000;

6. JOIN

问题:SQL中有哪些类型的JOIN?

答案

  • INNER JOIN:内连接,只返回两个表中匹配的行。
  • LEFT JOIN:左连接,返回左表的所有行,右表匹配的行,不匹配的用NULL填充。
  • RIGHT JOIN:右连接,返回右表的所有行,左表匹配的行,不匹配的用NULL填充。
  • FULL JOIN:全连接,返回两个表的所有行,不匹配的用NULL填充。
  • CROSS JOIN:交叉连接,返回两个表的笛卡尔积。

示例

sql
-- 内连接
SELECT * FROM orders
INNER JOIN customers ON orders.customer_id = customers.id;

-- 左连接
SELECT * FROM orders
LEFT JOIN customers ON orders.customer_id = customers.id;

-- 右连接
SELECT * FROM orders
RIGHT JOIN customers ON orders.customer_id = customers.id;

-- 全连接
SELECT * FROM orders
FULL JOIN customers ON orders.customer_id = customers.id;

7. 子查询

问题:什么是子查询?子查询有哪些类型?

答案

  • 子查询:嵌套在另一个查询中的查询。
  • 类型
    • 标量子查询:返回单个值的子查询。
    • 列子查询:返回单列的子查询。
    • 行子查询:返回单行的子查询。
    • 表子查询:返回多行多列的子查询。

示例

sql
-- 标量子查询
SELECT * FROM employees
WHERE salary > (SELECT AVG(salary) FROM employees);

-- 列子查询
SELECT * FROM employees
WHERE department_id IN (SELECT id FROM departments WHERE name = 'IT');

-- 表子查询
SELECT * FROM (SELECT * FROM employees WHERE salary > 5000) AS high_salary_employees;

8. 聚合函数

问题:SQL中有哪些常用的聚聚合函数?

答案

  • COUNT:计算行数。
  • SUM:计算总和。
  • AVG:计算平均值。
  • MAX:计算最大值。
  • MIN:计算最小值。

示例

sql
-- 计算员工总数
SELECT COUNT(*) FROM employees;

-- 计算工资总和
SELECT SUM(salary) FROM employees;

-- 计算平均工资
SELECT AVG(salary) FROM employees;

-- 计算最高工资
SELECT MAX(salary) FROM employees;

-- 计算最低工资
SELECT MIN(salary) FROM employees;

9. DISTINCT

问题:DISTINCT有什么作用?

答案

  • DISTINCT:用于去除结果集中的重复行。

示例

sql
-- 查询所有不重复的部门
SELECT DISTINCT department FROM employees;

-- 查询所有不重复的部门和职位组合
SELECT DISTINCT department, position FROM employees;

10. UNION

问题:UNION和UNION ALL有什么区别?

答案

  • UNION:合并两个查询的结果集,去除重复行。
  • UNION ALL:合并两个查询的结果集,保留重复行。

示例

sql
-- UNION
SELECT name FROM employees
UNION
SELECT name FROM customers;

-- UNION ALL
SELECT name FROM employees
UNION ALL
SELECT name FROM customers;

11. 事务

问题:什么是事务?事务的ACID特性是什么?

答案

  • 事务:一组数据库操作,要么全部成功,要么全部失败。
  • ACID特性
    • 原子性(Atomicity):事务是不可分割的工作单位,要么全部成功,要么全部失败。
    • 一致性(Consistency):事务执行前后,数据库从一个一致性状态变换到另一个一致性状态。
    • 隔离性(Isolation):事务的执行不受其他事务的干扰。
    • 持久性(Durability):事务一旦提交,对数据库的修改是永久的。

12. 事务隔离级别

问题:事务有哪些隔离级别?

答案

  • READ UNCOMMITTED:读取未提交的数据,可能导致脏读、不可重复读、幻读。
  • READ COMMITTED:读取已提交的数据,可能导致不可重复读、幻读。
  • REPEATABLE READ:可重复读,可能导致幻读。
  • SERIALIZABLE:串行化,最严格的隔离级别,避免所有并发问题。

13. 索引

问题:什么是索引?索引有什么作用?

答案

  • 索引:数据库中用于提高查询速度的数据结构。
  • 作用
    • 提高查询速度。
    • 减少IO操作。
    • 提高排序和分组效率。

示例

sql
-- 创建索引
CREATE INDEX idx_name ON employees(name);

-- 创建复合索引
CREATE INDEX idx_name_age ON employees(name, age);

-- 删除索引
DROP INDEX idx_name ON employees;

14. 视图

问题:什么是视图?视图有什么作用?

答案

  • 视图:虚拟表,基于一个或多个表的查询结果。
  • 作用
    • 简化复杂查询。
    • 保护敏感数据。
    • 提供数据独立性。

示例

sql
-- 创建视图
CREATE VIEW employee_view AS
SELECT id, name, department, salary
FROM employees
WHERE salary > 5000;

-- 使用视图
SELECT * FROM employee_view;

-- 删除视图
DROP VIEW employee_view;

15. 存储过程

问题:什么是存储过程?如何创建存储过程?

答案

  • 存储过程:预编译的SQL语句集合,存储在数据库中。
  • 作用
    • 提高性能。
    • 减少网络传输。
    • 提高安全性。

示例

sql
-- 创建存储过程
CREATE PROCEDURE get_employees_by_department(IN dept_name VARCHAR(50))
BEGIN
    SELECT * FROM employees WHERE department = dept_name;
END;

-- 调用存储过程
CALL get_employees_by_department('IT');

-- 删除存储过程
DROP PROCEDURE get_employees_by_department;

16. 触发器

问题:什么是触发器?如何创建触发器?

答案

  • 触发器:在特定事件发生时自动执行的SQL语句。
  • 作用
    • 自动维护数据一致性。
    • 实现复杂的业务逻辑。
    • 记录数据变更。

示例

sql
-- 创建触发器
CREATE TRIGGER before_employee_insert
BEFORE INSERT ON employees
FOR EACH ROW
BEGIN
    SET NEW.create_time = NOW();
END;

-- 删除触发器
DROP TRIGGER before_employee_insert;

17. 约束

问题:SQL中有哪些约束?

答案

  • PRIMARY KEY:主键约束,唯一标识表中的每一行。
  • FOREIGN KEY:外键约束,确保引用完整性。
  • UNIQUE:唯一约束,确保列中的值唯一。
  • NOT NULL:非空约束,确保列中的值不为空。
  • CHECK:检查约束,确保列中的值满足指定条件。
  • DEFAULT:默认值约束,为列指定默认值。

示例

sql
-- 创建表时添加约束
CREATE TABLE employees (
    id INT PRIMARY KEY,
    name VARCHAR(50) NOT NULL,
    age INT CHECK (age >= 18),
    department_id INT,
    FOREIGN KEY (department_id) REFERENCES departments(id)
);

-- 添加约束
ALTER TABLE employees ADD UNIQUE(email);

-- 删除约束
ALTER TABLE employees DROP FOREIGN KEY fk_department;

18. 分页查询

问题:如何实现分页查询?

答案

sql
-- MySQL分页
SELECT * FROM employees
LIMIT 10 OFFSET 0;

-- Oracle分页
SELECT * FROM (
    SELECT a.*, ROWNUM rn FROM (
        SELECT * FROM employees
    ) a WHERE ROWNUM <= 10
) WHERE rn > 0;

-- SQL Server分页
SELECT * FROM employees
ORDER BY id
OFFSET 0 ROWS FETCH NEXT 10 ROWS ONLY;

19. 窗口函数

问题:什么是窗口函数?常用的窗口函数有哪些?

答案

  • 窗口函数:在不改变行数的情况下,对结果集进行计算的函数。
  • 常用窗口函数
    • ROW_NUMBER:为每行分配一个唯一的序号。
    • RANK:为每行分配一个排名,相同值的行排名相同。
    • DENSE_RANK:为每行分配一个排名,相同值的行排名相同,排名连续。
    • LAG:获取当前行之前某行的值。
    • LEAD:获取当前行之后某行的值。
    • SUM、AVG、MAX、MIN:在窗口内计算聚合值。

示例

sql
-- ROW_NUMBER
SELECT name, salary,
       ROW_NUMBER() OVER (ORDER BY salary DESC) AS rank
FROM employees;

-- LAG
SELECT name, salary,
       LAG(salary, 1) OVER (ORDER BY id) AS prev_salary
FROM employees;

-- SUM
SELECT name, salary,
       SUM(salary) OVER (ORDER BY id) AS total_salary
FROM employees;

20. CTE

问题:什么是CTE(Common Table Expression)?如何使用?

答案

  • CTE:公共表表达式,用于创建临时结果集。
  • 作用
    • 提高查询的可读性。
    • 简化复杂查询。
    • 支持递归查询。

示例

sql
-- CTE
WITH employee_cte AS (
    SELECT id, name, salary
    FROM employees
    WHERE salary > 5000
)
SELECT * FROM employee_cte;

-- 递归CTE
WITH RECURSIVE employee_tree AS (
    SELECT id, name, manager_id, 1 AS level
    FROM employees
    WHERE manager_id IS NULL
    
    UNION ALL
    
    SELECT e.id, e.name, e.manager_id, et.level + 1
    FROM employees e
    JOIN employee_tree et ON e.manager_id = et.id
)
SELECT * FROM employee_tree;

21. 数据类型

问题:SQL中有哪些常用的数据类型?

答案

  • 数值类型:INT、BIGINT、FLOAT、DOUBLE、DECIMAL等。
  • 字符串类型:CHAR、VARCHAR、TEXT等。
  • 日期时间类型:DATE、TIME、DATETIME、TIMESTAMP等。
  • 布尔类型:BOOLEAN、BIT等。
  • 二进制类型:BINARY、VARBINARY、BLOB等。

22. NULL值

问题:NULL值有什么特点?如何处理NULL值?

答案

  • NULL值:表示未知或缺失的值。
  • 特点
    • NULL不等于任何值,包括NULL本身。
    • NULL参与运算,结果为NULL。
  • 处理方式
    • 使用IS NULL或IS NOT NULL判断NULL值。
    • 使用COALESCE函数将NULL值替换为默认值。
    • 使用IFNULL函数(MySQL)或ISNULL函数(SQL Server)。

示例

sql
-- 判断NULL值
SELECT * FROM employees WHERE name IS NULL;

-- 替换NULL值
SELECT COALESCE(name, 'Unknown') AS name FROM employees;

-- IFNULL函数(MySQL)
SELECT IFNULL(name, 'Unknown') AS name FROM employees;

23. 日期函数

问题:SQL中有哪些常用的日期函数?

答案

  • NOW():获取当前日期和时间。
  • CURDATE():获取当前日期。
  • CURTIME():获取当前时间。
  • DATE_ADD():日期加法。
  • DATE_SUB():日期减法。
  • DATEDIFF():计算日期差。
  • DATE_FORMAT():格式化日期。

示例

sql
-- 获取当前日期和时间
SELECT NOW();

-- 日期加法
SELECT DATE_ADD(NOW(), INTERVAL 1 DAY);

-- 计算日期差
SELECT DATEDIFF('2025-01-01', '2024-01-01');

-- 格式化日期
SELECT DATE_FORMAT(NOW(), '%Y-%m-%d %H:%i:%s');

24. 字符串函数

问题:SQL中有哪些常用的字符串函数?

答案

  • CONCAT():连接字符串。
  • SUBSTRING():截取字符串。
  • LENGTH():获取字符串长度。
  • UPPER():转换为大写。
  • LOWER():转换为小写。
  • TRIM():去除字符串两端的空格。
  • REPLACE():替换字符串。

示例

sql
-- 连接字符串
SELECT CONCAT('Hello', ' ', 'World');

-- 截取字符串
SELECT SUBSTRING('Hello, World!', 1, 5);

-- 获取字符串长度
SELECT LENGTH('Hello, World!');

-- 转换为大写
SELECT UPPER('hello');

-- 转换为小写
SELECT LOWER('HELLO');

-- 去除空格
SELECT TRIM('  Hello  ');

-- 替换字符串
SELECT REPLACE('Hello, World!', 'World', 'Java');

25. SQL优化

问题:如何优化SQL查询?

答案

  • 使用索引:为经常查询的列创建索引。
  • **避免SELECT ***:只查询需要的列。
  • 使用EXPLAIN:分析查询执行计划。
  • 避免子查询:使用JOIN代替子查询。
  • 使用LIMIT:限制返回的行数。
  • 避免使用OR:使用IN代替OR。
  • 使用EXISTS代替IN:EXISTS通常比IN快。
  • 避免使用LIKE '%xxx%':使用全文索引。
  • 使用UNION ALL代替UNION:如果不需要去重。
  • 使用批量插入:减少INSERT语句的次数。