提问人:Sharath K P 提问时间:11/10/2020 更新时间:11/11/2020 访问量:440
将 SQL 参数替换为 ?在单引号( ' ) [重复] 内不起作用
Substitute SQL parameter with ? is not working inside single quote( ' ) [duplicate]
问:
这个问题在这里已经有答案了:
java setString() 不起作用 (1 答案)
如何修复:“参数索引超出范围(参数数为 2 >,即 1)”。 (1 个答案)
错误:参数索引超出范围(参数数为 2 >,即 1)( 2 个答案)
3年前关闭。
我正在尝试使用SqlExecuter运行查询,方法是替换以下SQL单引号内的占位符(?)
SQL: SELECT name, sum(marks) FROM scores WHERE datetime >= now() - interval '?hours' 按名称分组;
我正在尝试替换参数的 Java 代码
Integer hourCount = 72; //String type also did not work
SQL_QUERY = "SELECT name, sum(marks) FROM scores WHERE datetime >= now() - interval '? hours' GROUP BY name;"
Map<String, Integer> scoreCount = new HashMap<>();
SqlExecutor sqlExecutor = new SqlExecutor(dbConfig);
scoreCount = sqlExecutor.executeForResultSet(SQL_QUERY, resultSet -> {
Map<String, Integer> results = new HashMap<>();
while (resultSet.next()) {
results.put(resultSet.getString(1), resultSet.getInt(2));
}
return results;
}, hourCount);
我收到上述代码片段的以下异常
09/Nov/2020 20:47:05:271 [ajp-apr-127.0.0.1-8019-exec-5] ERROR com.xyz.admin.utils.abc getScoreCount - org.postgresql.util.PSQLException: The column index is out of range: 1, number of columns: 0.
org.postgresql.util.PSQLException: The column index is out of range: 1, number of columns: 0.
at org.postgresql.core.v3.SimpleParameterList.bind(SimpleParameterList.java:56)
at org.postgresql.core.v3.SimpleParameterList.setBinaryParameter(SimpleParameterList.java:122)
at org.postgresql.jdbc2.AbstractJdbc2Statement.bindBytes(AbstractJdbc2Statement.java:2312)
at org.postgresql.jdbc2.AbstractJdbc2Statement.setInt(AbstractJdbc2Statement.java:1288)
at org.postgresql.jdbc2.AbstractJdbc2Statement.setObject(AbstractJdbc2Statement.java:1900)
at org.postgresql.jdbc3g.AbstractJdbc3gStatement.setObject(AbstractJdbc3gStatement.java:36)
at org.postgresql.jdbc4.AbstractJdbc4Statement.setObject(AbstractJdbc4Statement.java:48)
在在线检查问题时,根据 https://github.com/Microsoft/mssql-jdbc/issues/932, 它建议将单引号内的整个字符串内容作为参数传递,如下所示。还提到,在构造查询时,PreparedStatement 会自动在传递的参数周围添加引号
String hourCount = 72;
sqlExecutor.executeForResultSet("SELECT name, sum(marks) FROM scores WHERE datetime >= now() - interval ? GROUP BY name;", resultSet -> {
Map<String, Integer> results = new HashMap<>();
while (resultSet.next()) {
results.put(resultSet.getString(1), resultSet.getInt(2));
}
return results;
}, hourCount + " hours");
这导致了以下错误
09/Nov/2020 21:21:56:594 [ajp-apr-127.0.0.1-8019-exec-2] ERROR com.xyz.tips.admin.utils.abc getScoreCount - org.postgresql.util.PSQLException: ERROR: syntax error at or near "$1"
Position: 84
org.postgresql.util.PSQLException: ERROR: syntax error at or near "$1"
Position: 84
at org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:2270)
at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:1998)
at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:255)
at org.postgresql.jdbc2.AbstractJdbc2Statement.execute(AbstractJdbc2Statement.java:570)
at org.postgresql.jdbc2.AbstractJdbc2Statement.executeWithFlags(AbstractJdbc2Statement.java:420)
at org.postgresql.jdbc2.AbstractJdbc2Statement.executeQuery(AbstractJdbc2Statement.java:305)
at com.avenda.tips.utils.sql.AbstractJdbcOperations$3.run(AbstractJdbcOperations.java:64)
at com.avenda.tips.utils.sql.AbstractJdbcOperations$2.run(AbstractJdbcOperations.java:46)
at com.avenda.tips.utils.sql.SqlExecutor.execute(SqlExecutor.java:32)
at com.avenda.tips.utils.sql.AbstractJdbcOperations.execute(AbstractJdbcOperations.java:40)
at com.avenda.tips.utils.sql.AbstractJdbcOperations.executeForResultSet(AbstractJdbcOperations.java:59)
由于以上两种方法都不起作用,因此我使用
SQL_QUERY = "SELECT name, sum(marks) FROM scores WHERE datetime >= now() - interval '? hours' GROUP BY name;"
SQL_QUERY.replace("?", hourCount)
我能知道我在这里缺少什么,以及如何在查询包含上述单引号时避免 sql 注入吗?
答:
0赞
Laurenz Albe
11/10/2020
#1
是的,字符串文本中的问号不会被视为参数,也不会被替换。
试试这个:
SQL_QUERY = "SELECT name, sum(marks) FROM scores WHERE datetime >= now() - interval '1 hour' * ? GROUP BY name;"
评论
0赞
Sharath K P
11/10/2020
按预期工作。谢谢!还找到了具有 make 间隔功能的替代解决方案。
评论
make_interval()