String sql = "update emp set ?=? where empno=?"; // ❌ 錯誤
ps = conn.prepareStatement(sql);
ps.setString(1, oldInfo); // 欄位名
ps.setInt(2, infoInt); // 欄位值
ps.setInt(3, empId); // 條件值
java.sql.SQLSyntaxErrorException: ORA-01747: user.table.column, table.column 或列說明無效
JDBC PreparedStatement 的佔位符 ? 僅能替代「值」(Value),不能替代「標識符」(Identifier),如表名、欄位名、Schema 名。
// 假設 oldInfo 經過白名單驗證,確認為合法欄位名
String sql = "update emp set " + oldInfo + " = ? where empno = ?";
ps = conn.prepareStatement(sql);
ps.setInt(1, infoInt); // 參數索引從 1 重新計算
ps.setInt(2, empId);
count = ps.executeUpdate();
private static final Map COLUMN_MAP = Map.of(
"salary", "SAL",
"comm", "COMM",
"deptno", "DEPTNO"
);
public void updateEmpField(String fieldKey, Object newValue, int empNo) {
String column = COLUMN_MAP.get(fieldKey);
if (column == null) throw new IllegalArgumentException("非法欄位: " + fieldKey);
String sql = "update emp set " + column + " = ? where empno = ?";
try (PreparedStatement ps = conn.prepareStatement(sql)) {
ps.setObject(1, newValue);
ps.setInt(2, empNo);
ps.executeUpdate();
}
}
setXxx() 綁定${column}(MyBatis)或 Criteria API 避免手寫 SQL<update id="updateEmpField">
update emp
<set>
<!-- ${} 直接拼接,需確保 column 經過驗證 -->
${column} = #{value}
</set>
where empno = #{empNo}
</update>
記住鐵律:佔位符只能放值,結構必須寫死或經白名單驗證後拼接。