Files
2025-09-25 03:32:26 +08:00

64 lines
2.3 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
### 有哪些 SQL 语句无法使用预编译的方式
**1. 动态的数据库对象名称**
预编译的参数只能用于替换 SQL 语句中的**值**(`VALUES`),而不能用于替换**表名**、**列名**、**排序字段**(`ORDER BY`)或**数据库名**
例如,你不能这样做:
```java
// 错误的预编译用法
String sql = "SELECT * FROM ? WHERE id = 1";
PreparedStatement pstmt = conn.prepareStatement(sql);
pstmt.setString(1, "users"); // 无法将表名作为参数传入
```
**2. 动态的 SQL 关键词或子句**
`SELECT``FROM``WHERE``GROUP BY``ORDER BY `等 SQL 关键词或整个子句都无法作为参数传入
例如,如果你想根据用户输入动态改变排序规则,你不能这样做:
```java
// 错误的预编译用法
String sql = "SELECT * FROM products ORDER BY ?";
PreparedStatement pstmt = conn.prepareStatement(sql);
pstmt.setString(1, "price DESC"); // 无法将排序规则作为参数传入
```
**3. 动态的 `IN` 子句中的值列表**
`IN` 子句中的值列表长度是可变的,预编译的占位符数量是固定的。因此,你不能直接将整个列表作为参数传入
例如,如果你想查询多个ID的用户,不能这样做:
```java
// 错误的预编译用法
String sql = "SELECT * FROM users WHERE id IN (?)";
PreparedStatement pstmt = conn.prepareStatement(sql);
pstmt.setString(1, "101, 102, 103"); // 字符串“101, 102, 103”会被当作一个值
```
**正确的做法:动态生成占位符**
对于这种情况,你需要在代码中根据用户输入的列表动态生成相应数量的占位符
```java
// 正确的做法
List<Integer> userIds = getUserIdsFromInput(); // 假设用户输入:101, 102, 103
StringBuilder sqlBuilder = new StringBuilder("SELECT * FROM users WHERE id IN (");
for (int i = 0; i < userIds.size(); i++) {
sqlBuilder.append("?");
if (i < userIds.size() - 1) {
sqlBuilder.append(", ");
}
}
sqlBuilder.append(")");
String sql = sqlBuilder.toString(); // 生成的SQLSELECT * FROM users WHERE id IN (?, ?, ?)
PreparedStatement pstmt = conn.prepareStatement(sql);
for (int i = 0; i < userIds.size(); i++) {
pstmt.setInt(i + 1, userIds.get(i));
}
ResultSet rs = pstmt.executeQuery();
```