1. SQL常用语句基础大全:从零开始掌握数据库操作
刚接触数据库时,我经常被各种SQL语句搞得晕头转向。直到后来在实际项目中反复使用,才发现掌握基础SQL语句就像学会了数据库的"普通话"——它能让你与任何关系型数据库顺畅交流。这篇文章将分享我十年来总结的SQL基础语句大全,涵盖增删改查、聚合函数、表连接等核心操作,每个语法都配有真实场景示例和避坑指南。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 基础查询语句:SELECT的十八般武艺
2.1 最简单的数据检索
sql复制SELECT * FROM employees;
这个星号(*)代表所有字段,但在生产环境要慎用——它会增加数据库I/O负担。建议明确指定字段:
sql复制SELECT employee_id, first_name, last_name FROM employees;
注意:在千万级数据表中,SELECT *可能导致网络阻塞和内存溢出
2.2 条件过滤的精准打击
WHERE子句是SQL的筛选器:
sql复制-- 基本条件查询
SELECT * FROM products WHERE price > 100;
-- 多条件组合
SELECT * FROM orders
WHERE order_date >= '2023-01-01'
AND status = 'completed';
-- 模糊查询(LIKE)
SELECT * FROM customers
WHERE email LIKE '%@gmail.com';
特殊场景处理:
sql复制-- NULL值判断要用IS NULL
SELECT * FROM users WHERE phone IS NULL;
-- 范围查询(BETWEEN包含边界值)
SELECT * FROM products
WHERE price BETWEEN 50 AND 100;
3. 数据操作语言:增删改的实战技巧
3.1 插入数据的正确姿势
基础INSERT语句:
sql复制INSERT INTO customers (name, email, created_at)
VALUES ('张三', 'zhangsan@example.com', NOW());
批量插入能提升10倍性能:
sql复制INSERT INTO products (name, price, stock) VALUES
('鼠标', 99.9, 100),
('键盘', 199, 50),
('显示器', 899, 20);
3.2 更新数据的避坑指南
基本更新操作:
sql复制UPDATE users SET last_login = NOW()
WHERE user_id = 1001;
危险操作警示:
sql复制-- 没有WHERE条件的UPDATE会更新整表!
UPDATE products SET price = price * 1.1; -- 所有商品涨价10%
3.3 删除数据的注意事项
基础删除:
sql复制DELETE FROM temp_logs WHERE created_at < '2022-01-01';
重要建议:
sql复制-- 先SELECT确认要删除的记录
SELECT * FROM candidates
WHERE interview_score < 60;
-- 再执行DELETE(条件必须与SELECT一致)
DELETE FROM candidates
WHERE interview_score < 60;
4. 高级查询技术:让数据开口说话
4.1 聚合函数与分组统计
常用聚合函数:
sql复制-- 基本统计
SELECT
COUNT(*) AS total_orders,
SUM(amount) AS total_sales,
AVG(amount) AS avg_order,
MAX(created_at) AS latest_order
FROM orders;
-- 分组统计
SELECT
department_id,
COUNT(*) AS employee_count,
AVG(salary) AS avg_salary
FROM employees
GROUP BY department_id;
4.2 多表连接的三种武器
- INNER JOIN(内连接):
sql复制SELECT
o.order_id,
c.customer_name,
o.order_date
FROM orders o
INNER JOIN customers c ON o.customer_id = c.customer_id;
- LEFT JOIN(左连接):
sql复制-- 查询所有部门及员工(包括无员工的部门)
SELECT
d.department_name,
e.employee_name
FROM departments d
LEFT JOIN employees e ON d.department_id = e.department_id;
- 自连接查询:
sql复制-- 查找同一部门的员工对
SELECT
a.employee_name AS employee1,
b.employee_name AS employee2
FROM employees a
JOIN employees b ON a.department_id = b.department_id
WHERE a.employee_id < b.employee_id;
5. 实用进阶技巧:工作中最常用的SQL语句
5.1 分页查询的标准化写法
MySQL分页:
sql复制SELECT * FROM products
ORDER BY price DESC
LIMIT 10 OFFSET 20; -- 第3页,每页10条
Oracle/SQL Server分页:
sql复制-- Oracle
SELECT * FROM (
SELECT t.*, ROWNUM rn FROM (
SELECT * FROM products ORDER BY price DESC
) t WHERE ROWNUM <= 30
) WHERE rn > 20;
-- SQL Server
SELECT * FROM products
ORDER BY price DESC
OFFSET 20 ROWS FETCH NEXT 10 ROWS ONLY;
5.2 子查询的灵活应用
WHERE子句中的子查询:
sql复制-- 找出高于平均价格的商品
SELECT * FROM products
WHERE price > (SELECT AVG(price) FROM products);
FROM子句中的子查询:
sql复制-- 按部门统计平均工资
SELECT
d.department_name,
stats.avg_salary
FROM departments d
JOIN (
SELECT
department_id,
AVG(salary) AS avg_salary
FROM employees
GROUP BY department_id
) stats ON d.department_id = stats.department_id;
5.3 常见日期处理函数
sql复制-- 获取当前日期
SELECT CURRENT_DATE(); -- MySQL
SELECT GETDATE(); -- SQL Server
-- 日期格式化
SELECT DATE_FORMAT(order_date, '%Y-%m') AS month
FROM orders; -- MySQL
-- 日期加减
SELECT DATE_ADD(CURRENT_DATE, INTERVAL 7 DAY); -- MySQL
6. SQL优化与避坑指南
6.1 索引使用原则
- 为WHERE、JOIN、ORDER BY字段建索引
- 避免在索引列上使用函数:
sql复制-- 坏例子(索引失效)
SELECT * FROM users WHERE YEAR(create_time) = 2023;
-- 好例子
SELECT * FROM users
WHERE create_time BETWEEN '2023-01-01' AND '2023-12-31';
6.2 EXPLAIN执行计划分析
sql复制EXPLAIN SELECT * FROM orders
WHERE customer_id IN (SELECT customer_id FROM customers WHERE vip = 1);
关键指标解读:
- type:ALL(全表扫描) → index → range → ref → eq_ref → const
- rows:预估扫描行数
- Extra:Using filesort(需要额外排序) / Using temporary(使用临时表)
6.3 事务处理的ACID原则
sql复制START TRANSACTION;
UPDATE accounts SET balance = balance - 100
WHERE user_id = 1;
UPDATE accounts SET balance = balance + 100
WHERE user_id = 2;
-- 只有两条更新都成功才提交
COMMIT;
-- 任一失败则回滚
-- ROLLBACK;
7. 面试常见SQL问题解析
7.1 排名问题解决方案
使用窗口函数:
sql复制-- 各部门工资排名
SELECT
employee_name,
department_id,
salary,
RANK() OVER (PARTITION BY department_id ORDER BY salary DESC) AS dept_rank
FROM employees;
7.2 连续登录天数计算
sql复制WITH login_dates AS (
SELECT
user_id,
login_date,
login_date - ROW_NUMBER() OVER (PARTITION BY user_id ORDER BY login_date) AS grp
FROM user_logins
WHERE DATE(login_date) BETWEEN '2023-01-01' AND '2023-01-31'
)
SELECT
user_id,
COUNT(*) AS consecutive_days
FROM login_dates
GROUP BY user_id, grp
HAVING COUNT(*) >= 7; -- 查找连续登录7天以上的用户
7.3 留存率计算
sql复制SELECT
DATE(a.login_date) AS day,
COUNT(DISTINCT a.user_id) AS dau,
COUNT(DISTINCT b.user_id) AS next_day_retained,
ROUND(COUNT(DISTINCT b.user_id) * 100.0 / COUNT(DISTINCT a.user_id), 2) AS retention_rate
FROM user_logins a
LEFT JOIN user_logins b ON a.user_id = b.user_id
AND DATE(b.login_date) = DATE(a.login_date) + INTERVAL 1 DAY
WHERE DATE(a.login_date) = '2023-01-01'
GROUP BY DATE(a.login_date);
8. 实际工作中的SQL最佳实践
- 始终为生产环境的DELETE/UPDATE添加WHERE条件
- 大批量操作使用事务分批提交
- 复杂查询先EXPLAIN分析执行计划
- 定期收集统计信息:
ANALYZE TABLE tablename - 避免在WHERE子句中对字段进行运算
- 多表连接时明确指定JOIN条件
- 使用SQL_FORMATTER工具保持代码风格一致
- 重要操作前备份数据:
CREATE TABLE backup_20230701 AS SELECT * FROM original_table
我见过最惨痛的教训是开发同学在凌晨执行UPDATE忘记加WHERE条件,导致全表2000万数据被错误更新。当时没有有效备份,最终只能通过日志恢复,整个团队通宵了三天。所以现在我养成了习惯——在执行任何写操作前,先用相同的WHERE条件做SELECT确认影响范围。
