将SQL参数替换为?在单引号'中不起作用

问题描述

我正在尝试通过替换以下sql的单引号内的占位符(?)来使用sqlExecuter运行查询

sql:SELECT名称,总和(标记)从分数WHERE日期时间> = Now()-间隔'?小时的GROUP BY名称

我正在尝试替换参数的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;",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字符串

sql_QUERY = "SELECT name,sum(marks) FROM scores WHERE datetime >= Now() - interval '? hours' GROUP BY name;"
sql_QUERY.replace("?",hourCount) 

我能知道我在这里缺少什么吗?当查询包含上述单引号时如何避免sql注入?

解决方法

是的,字符串文字内的问号不会被视为参数,也不会被替换。

尝试一下:

SQL_QUERY = "SELECT name,sum(marks) FROM scores WHERE datetime >= now() - interval '1 hour' * ? GROUP BY name;"