【问题标题】:Building a String parameter (with SQL content) from resource file for SQL PreparedStatement从 SQL PreparedStatement 的资源文件构建字符串参数(带有 SQL 内容)
【发布时间】:2013-07-26 01:43:10
【问题描述】:

我需要使用 jdbc 在 Java 中执行 SQL PreparedStatement。 我遇到了其中一个参数的问题,因为它具有 SQL 内容以及来自资源文件的字符串。 它看起来像这样:

所需的 SQL:

SELECT * FROM Table T WHERE T.value = 10 AND T.display IN ('Sample1', 'Sample2')

在上述查询中,Sample1Sample2 值必须通过参数传递给 PreparedStatement。

PreparedStatement:

SELECT * FROM Table T WHERE T.value = 10 ?

在我的应用程序代码中,我设置的参数如下:

statement.setString(1, "AND T.display IN ('Sample1', 'Sample2')");

但是这并没有返回适当的结果。

考虑到它也有 SQL 内容和字符串,有没有更好的方法来构建这个特定的参数?

编辑: Sample1, Sample2 等是在运行时从外部文件中检索的字符串,每次可以有不同数量的这些字符串。 IE。只能有一个字符串Sample1或多个字符串Sample1, Sample2, Sample3, etc.

EDIT2: 使用的数据库是 Oracle。

【问题讨论】:

  • 您能否详细说明“但是这并没有返回适当的结果”?
  • 查询没有被拒绝,但问题似乎在于参数中添加了双引号。
  • 你可能想指定你正在使用的数据库
  • 同时打印生成的sql语句
  • @Amine 我认为无法检查生成的 SQL。 stackoverflow.com/a/2382561/1505128

标签: java sql jdbc prepared-statement


【解决方案1】:

? 占位符只能用于查询中需要值的位置。在任何其他位置有一个?(如您的问题:WHERE T.value = 10 ?)只是一个语法错误。

换句话说:不可能像您尝试做的那样对查询本身的一部分进行参数化;您只能参数化值。如果您需要添加动态数量的参数,则需要通过添加所需数量的参数并使用setString() 来动态构造查询。例如:

StringBuilder sb = new StringBuilder(
     "SELECT * FROM Table T WHERE T.value = 10 AND T.display IN (?");
// Note: intentionally starting at 1, first parameter already above
// Assuming always at least 1 parameter
while (int i = 1; i < params.length; i++) {
    sb.append(", ?");
}
sb.append(')');

try (
    PreparedStatement pstmt = con.prepareStatement(sb.toString())
) {
    for (int i = 0; i < params.length; i++) {
        pstmt.setString(i + 1, params[i]);
    }
    try (
        ResultSet rs = pstmt.executeQuery();
    ) {
        // Use resultset
    }
}

【讨论】:

    【解决方案2】:

    将其用作 PreparedStatement

    "SELECT * FROM Table T WHERE T.value = 10 AND T.display IN (?, ?);"
    

    然后调用

    statement.setString(1, "Sample1");
    statement.setString(2, "Sample2");
    

    在执行语句之前。


    更新:

    String generateParamString(int params) {
        StringBuilder sb = new StringBuilder("(");
        for (int i = 1; i < params; i++) {
            sb.append("?, ");
        }
        sb.append("?)");
        return sb.toString();
    }
    
    List<String> samples = ... // your list with samples.
    String stmtString = "SELECT * FROM Table T WHERE T.value = 10 AND T.display IN "
        + generateParamString(samples.size());
    // generate statement with stmtString 
    for (int i = 0; i < samples.size(); i++) {
        statement.setString(i + 1, samples.get(i));
    }
    // execute statement...
    

    【讨论】:

    • 请查看问题中的编辑。这些字符串不一定只有 2 个。所以硬编码(?,?) 不是一种选择。
    • @naren.katneni 好吧,如果硬编码不是一种选择 - 动态创建 (?,?,? ... ?) 字符串
    • @naren.katneni 您的示例字符串来自哪里?数组、列表、集合还是其他?
    • @jlordo 它们存储在从 XML 文件生成的列表中。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-10-09
    • 1970-01-01
    • 2013-11-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多