好的,以下是从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.建表示例(带常见约束)
CREATETABLEstudent(idINTPRIMARYKEYAUTO_INCREMENT,-- 主键 + 自增student_noVARCHAR(20)UNIQUENOTNULL,-- 学号唯一 + 非空nameVARCHAR(50)NOTNULL,genderCHAR(1)DEFAULT'M'CHECK(genderIN('M','F')),-- 默认值 + 检查约束ageINTCHECK(age>=10ANDage<=50),scoreDECIMAL(5,2),class_idINT,create_timeDATETIMEDEFAULTCURRENT_TIMESTAMP,FOREIGNKEY(class_id)REFERENCESclass(id)-- 外键约束ONDELETESETNULLONUPDATECASCADE);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 风格)
importjava.sql.*;publicclassSqlDemo{privatestaticfinalStringURL="jdbc:mysql://localhost:3306/school?useSSL=false&serverTimezone=Asia/Shanghai";privatestaticfinalStringUSER="root";privatestaticfinalStringPASS="123456";publicstaticvoidmain(String[]args){try(Connectionconn=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(SQLExceptione){e.printStackTrace();}}// 插入(推荐使用 PreparedStatement 防注入)staticvoidinsertStudent(Connectionconn,Stringname,intage,doublescore)throwsSQLException{Stringsql="INSERT INTO student (name, age, score) VALUES (?, ?, ?)";try(PreparedStatementps=conn.prepareStatement(sql)){ps.setString(1,name);ps.setInt(2,age);ps.setDouble(3,score);introws=ps.executeUpdate();System.out.println("插入成功,受影响行数:"+rows);}}// 查询:模糊 + 区间 + 排序 + 分页 + 去重示例staticvoidqueryStudents(Connectionconn,StringnameKeyword,intminAge,intmaxAge)throwsSQLException{// 写法1:推荐(清晰、安全)Stringsql=""" 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(PreparedStatementps=conn.prepareStatement(sql)){ps.setString(1,"%"+nameKeyword+"%");ps.setInt(2,minAge);ps.setInt(3,maxAge);try(ResultSetrs=ps.executeQuery()){while(rs.next()){System.out.printf("姓名:%s 年龄:%d 分数:%.1f%n",rs.getString("name"),rs.getInt("age"),rs.getDouble("score"));}}}}// 更新staticvoidupdateScore(Connectionconn,intid,doubleaddScore)throwsSQLException{Stringsql="UPDATE student SET score = score + ? WHERE id = ?";try(PreparedStatementps=conn.prepareStatement(sql)){ps.setDouble(1,addScore);ps.setInt(2,id);introws=ps.executeUpdate();System.out.println("更新成功,受影响行数:"+rows);}}// 删除staticvoiddeleteStudent(Connectionconn,intid)throwsSQLException{Stringsql="DELETE FROM student WHERE id = ?";try(PreparedStatementps=conn.prepareStatement(sql)){ps.setInt(1,id);introws=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、子查询、索引优化、事务、批量插入)?直接说,我继续给你展开最实用的代码和注意点。