准备语句 - 使用函数作为where子句的一部分

时间:2009-10-05 13:53:13

标签: java sql oracle prepared-statement

我正在使用Java预处理语句从Oracle数据库获取数据。由于某些性能问题,查询使用“虚拟列”作为索引。

查询如下所示:

String status = "processed";
String customerId = 123;
String query = "SELECT DISTINCT trans_id FROM trans WHERE status = " + status + " AND FN_GET_CUST_ID(trans.trans_id) = " + customerId;

Connection conn = getConnection();
PreparedStatement ps = null;
ResultSet rs = null;

try {
  ps = conn.prepareStatement(query);
  ps.execute();
  ...
} catch (...)

这不起作用。将该函数作为where子句的一部分会导致SQLException。我知道CallableStatement,并知道我可以先使用它然后连接结果。但是,此表使用FN_GET_CUST_ID(trans_id)作为其索引的一部分。有没有办法使用带有数据库函数的预准备语句作为查询参数?

3 个答案:

答案 0 :(得分:6)

  1. 永远不要将SQL的参数连接到String中。始终使用占位符(?)和setXxx(column, value);

  2. 如果您在自己喜欢的数据库工具中运行SQL,则会收到相同的错误。问题是Oracle出于某种原因无法使用该功能。你得到什么错误代码?

答案 1 :(得分:1)

如果客户ID是数字,请保留int而不是String。然后尝试执行以下操作:

String query = "SELECT DISTINCT trans_id FROM trans WHERE status = ? AND FN_GET_CUST_ID(trans.trans_id) = ?"; 

ps = conn.prepareStatement(query); 
ps.setString(1, status);
ps.setInt(2, customerId);
ps.execute();

除了预处理语句的其他好处之外,您不必记住字符串引用(这最有可能导致错误)并转义特殊字符。

答案 2 :(得分:0)

乍一看,查询似乎不正确。在使用status变量之前和之后,您缺少一个撇号(假设状态是varchar列)。

String query = "SELECT DISTINCT trans_id FROM trans 
WHERE status = '" + status + "' AND FN_GET_CUST_ID(trans.trans_id) = " + customerId;
编辑:我不是来自java背景。但是,正如@Aron所说,最好使用占位符&然后使用某种方法设置参数值以避免SQL Injection