好的,以下是从 Java 角度 学习 SQL 的最实用总结,重点覆盖你提到的所有操作:
- 插入(INSERT)
- 查询(SELECT)+ 过滤(WHERE)+ 排序(ORDER BY)+ 去重(DISTINCT / GROUP BY)
- 更新(UPDATE)
- 删除(DELETE)
- 返回限制行数(LIMIT / OFFSET)
- 字符串模糊查询(LIKE)
- 区间数据(BETWEEN / >= <=)
- 合并(UNION / UNION ALL)
- 常见约束(PRIMARY KEY、FOREIGN KEY、UNIQUE、NOT NULL、DEFAULT、CHECK)
全部以 MySQL 为例(Java 最常用),并附上 JDBC 简单执行方式。
1. 建表示例(带常见约束)
CREATE TABLE student (
id INT PRIMARY KEY AUTO_INCREMENT, -- 主键 + 自增
student_no VARCHAR(20) UNIQUE NOT NULL, -- 学号唯一 + 非空
name VARCHAR(50) NOT NULL,
gender CHAR(1) DEFAULT 'M' CHECK (gender IN ('M','F')), -- 默认值 + 检查约束
age INT CHECK (age >= 10 AND age <= 50),
score DECIMAL(5,2),
class_id INT,
create_time DATETIME DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (class_id) REFERENCES class(id) -- 外键约束
ON DELETE SET NULL ON UPDATE CASCADE
);
2. 常用 SQL 操作对照表(Java 视角)
| 操作 | SQL 写法示例 | JDBC 常见用法要点 | 说明 |
|---|---|---|---|
| 插入 | INSERT INTO student(name, age, score) VALUES('张三', 20, 88.5) | PreparedStatement + ? 防注入 | 单行 / 多行 / 从查询插入 |
| 查询全部 | SELECT * FROM student | executeQuery() → ResultSet | 开发中很少用 * |
| 过滤 | WHERE age > 18 AND score >= 60 | 多条件用 AND / OR | — |
| 模糊查询 | WHERE name LIKE '%李%' 或 LIKE '张_' | setString(1, "%" + keyword + "%") | % 任意字符,_ 单个字符 |
| 区间查询 | WHERE age BETWEEN 18 AND 25 或 age >= 18 AND age <= 25 | — | BETWEEN 包含边界 |
| 排序 | ORDER BY score DESC, age ASC | — | DESC 降序,ASC 升序(默认) |
| 去重 | SELECT DISTINCT name FROM student | — | 只对单列 / 多列组合去重 |
| 限制行数 | LIMIT 10 或 LIMIT 10 OFFSET 20(第21~30条) | 分页必用 | MySQL 专用(PostgreSQL 用 OFFSET … FETCH) |
| 更新 | UPDATE student SET score = score + 5 WHERE id = 1001 | 一定要加 WHERE! | — |
| 删除 | DELETE FROM student WHERE id = 1001 | 一定要加 WHERE! | TRUNCATE TABLE 更快但清空全部 |
| 合并查询 | (SELECT name FROM student WHERE score > 90) UNION (SELECT name FROM teacher) | — | UNION 去重,UNION ALL 不去重(性能更好) |
3. 完整示例代码(JDBC 风格)
import java.sql.*;
public class SqlDemo {
private static final String URL = "jdbc:mysql://localhost:3306/school?useSSL=false&serverTimezone=Asia/Shanghai";
private static final String USER = "root";
private static final String PASS = "123456";
public static void main(String[] args) {
try (Connection conn = DriverManager.getConnection(URL, USER, PASS)) {
// 1. 插入
insertStudent(conn, "李四", 19, 92.5);
// 2. 模糊查询 + 区间 + 排序 + 限制行数 + 去重
queryStudents(conn, "李", 18, 25);
// 3. 更新
updateScore(conn, 1, 5.0);
// 4. 删除
deleteStudent(conn, 100);
} catch (SQLException e) {
e.printStackTrace();
}
}
// 插入(推荐使用 PreparedStatement 防注入)
static void insertStudent(Connection conn, String name, int age, double score) throws SQLException {
String sql = "INSERT INTO student (name, age, score) VALUES (?, ?, ?)";
try (PreparedStatement ps = conn.prepareStatement(sql)) {
ps.setString(1, name);
ps.setInt(2, age);
ps.setDouble(3, score);
int rows = ps.executeUpdate();
System.out.println("插入成功,受影响行数:" + rows);
}
}
// 查询:模糊 + 区间 + 排序 + 分页 + 去重示例
static void queryStudents(Connection conn, String nameKeyword, int minAge, int maxAge) throws SQLException {
// 写法1:推荐(清晰、安全)
String sql = """
SELECT DISTINCT name, age, score
FROM student
WHERE name LIKE ?
AND age BETWEEN ? AND ?
ORDER BY score DESC, age ASC
LIMIT 10 OFFSET 0
""";
try (PreparedStatement ps = conn.prepareStatement(sql)) {
ps.setString(1, "%" + nameKeyword + "%");
ps.setInt(2, minAge);
ps.setInt(3, maxAge);
try (ResultSet rs = ps.executeQuery()) {
while (rs.next()) {
System.out.printf("姓名:%s 年龄:%d 分数:%.1f%n",
rs.getString("name"), rs.getInt("age"), rs.getDouble("score"));
}
}
}
}
// 更新
static void updateScore(Connection conn, int id, double addScore) throws SQLException {
String sql = "UPDATE student SET score = score + ? WHERE id = ?";
try (PreparedStatement ps = conn.prepareStatement(sql)) {
ps.setDouble(1, addScore);
ps.setInt(2, id);
int rows = ps.executeUpdate();
System.out.println("更新成功,受影响行数:" + rows);
}
}
// 删除
static void deleteStudent(Connection conn, int id) throws SQLException {
String sql = "DELETE FROM student WHERE id = ?";
try (PreparedStatement ps = conn.prepareStatement(sql)) {
ps.setInt(1, id);
int rows = ps.executeUpdate();
System.out.println("删除成功,受影响行数:" + rows);
}
}
}
4. 快速记忆口诀(面试/实战最常用)
- 增:
INSERT INTO 表 (字段) VALUES (值)→ 防注入用? - 删:
DELETE FROM 表 WHERE 条件→ 没 WHERE 就全删! - 改:
UPDATE 表 SET 字段=新值 WHERE 条件→ 没 WHERE 全改! - 查:
SELECT 字段 FROM 表 WHERE 条件 ORDER BY 排序 LIMIT 页大小 OFFSET 偏移 - 模糊:
LIKE '%关键词%'或LIKE '前缀%'(索引友好) - 去重:
DISTINCT(简单场景)或GROUP BY(配合聚合) - 合并:
UNION ALL>UNION(性能优先) - 分页:MySQL →
LIMIT offset, rows;PostgreSQL →OFFSET x LIMIT y
5. 常见坑 & 建议
| 问题 | 错误写法示例 | 正确/推荐写法 |
|---|---|---|
| SQL 注入 | WHERE name = '" + name + "' | 永远用 PreparedStatement + ? |
| 忘记 WHERE | UPDATE student SET score=0 | 开发/测试环境加 WHERE 1=0 保险 |
| 分页从 1 开始 | LIMIT 0,10(第1页) | 前端页码-1 转 offset |
| LIKE 前缀 % 失效索引 | LIKE '%abc' | 尽量用 LIKE 'abc%' 或全文索引 |
| 大数据合并 | UNION(去重慢) | 优先 UNION ALL + 业务去重 |
如果你当前用的是 MyBatis / Spring Data JPA / JdbcTemplate,可以告诉我,我再给你对应写法。
想深入哪个部分(比如多表 JOIN、子查询、索引优化、事务、批量插入)?直接说,我继续给你展开最实用的代码和注意点。