【问题标题】:Error in passing SQL command through a prepared statement via jdbc通过 jdbc 通过准备好的语句传递 SQL 命令时出错
【发布时间】:2012-06-06 21:00:40
【问题描述】:

我正在尝试创建程序在运行时获取行数和列数的表。

代码如下:

String sql = 
  "CREATE TABLE if not exists itemset (?";
up1 = con.prepareStatement(sql);
for(int j=1; j < ccolumns; j++) {
  sql += ",?";
}
sql += ")";
System.out.println(sql);
for(int j=1; j < ccolumns+1; j++) {
  System.out.println(j);
  up1.setString(j, "item"+j+" TINYINT(10)");
}
up1.executeQuery();

错误是

Parameter index out of range (2 &gt; number of parameters, which is 1)

在第二次迭代时出现在 setString 行中

【问题讨论】:

  • 也许你应该调用“prepare”你完成构建 SQL 字符串 ;)?
  • PreparedStatement 不应用于 CREATE TABLE sql。

标签: java jdbc prepared-statement sqlexception


【解决方案1】:

尝试移动

up1 = con.prepareStatement(sql); 

之后

System.out.println(sql);

【讨论】:

  • 这确实解决了之前的问题,但现在它给出了一个新问题对于5的ccolumns输入,sql语句似乎已更改为''item1 TINYINT(10)','item2 TINYINT (10)','item3 TINYINT(10)','item4 TINYINT(10)',' 必须有 5 个而不是 4 个(第二个循环正在迭代 5 次)
【解决方案2】:

虽然我没有验证,但我相信 Andriy 的回答是正确的。此外,您可能需要考虑使用StringBuilder 进行字符串累积,因为它们的重量较轻。下面更新了代码。

    StringBuilder sql = new StringBuilder("CREATE TABLE if not exists itemset (?");
    for (int j = 1; j < ccolumns; j++) {
        sql.append(",?");
    }
    sql.append(")");
    System.out.println(sql.toString());
    up1 = con.prepareStatement(sql.toString());
    for (int j = 1; j < ccolumns + 1; j++) {
        System.out.println(j);
        up1.setString(j, "item" + j + " TINYINT(10)");
    }
    up1.executeQuery();

【讨论】:

    【解决方案3】:

    您要修复的第一件事是,当您要更改它时,请不要使用String 实例。 String 实例是不可变的,当您修改已创建的 String 时,会创建新的修改实例并且它不是免费的。 您应该为此使用StringBuilder,它具有允许修改它而无需创建新实例的实例方法。我建议您在修改String 时始终使用StringBuilder。其次,您致电con.prepareStatement(sql),然后修改其sql字段。这不好不是吗? 所以只有在你使用 String 之后才添加它。

    String sql = 
      "CREATE TABLE if not exists itemset (?";
    for(int j=1; j < ccolumns; j++) {
      sql += ",?";
    }
    sql += ")";
    System.out.println(sql);
    up1 = con.prepareStatement(sql);
    for(int j=1; j < ccolumns+1; j++) {
      System.out.println(j);
      up1.setString(j, "item"+j+" TINYINT(10)");
    }
    up1.executeQuery();
    

    你不能用给定的String 调用prepareStatement 然后修改它。


    但更清洁和更快尝试这样做

    StringBuilder sqlStatement = new StringBuilder(
          "CREATE TABLE if not exists itemset (?");
        for(int j=1; j < ccolumns; j++) {
          sqlStatement.append(",?");
        }
        sqlStatement.append(")");
        up1 = con.prepareStatement(sqlStatement.toString());
        for(int j=1; j < ccolumns+1; j++) {
          System.out.println(j);
          up1.setString(j, "item"+j+" TINYINT(10)");
        }
        up1.executeQuery();
    

    【讨论】:

    • @PhilippReichart 抱歉,我看到后立即更换错误,已更正。
    • 错误是在字符串之前给出preparestatement,通过使用StringBuilder它仍然给出了我在回复andriy时提到的问题,无论如何我不知道StringBuilder谢谢
    【解决方案4】:

    PreparedStatement 不能用于 DDL 查询,例如问题中的 CREATE TABLE

    传递给setString() 的值在生成的 SQL 中被转义,导致发送到数据库的查询无效。

    当只给出列数时,只需创建 CREATE TABLE 语句(如其他人建议的那样使用StringBuilder)并使用普通的Statement 执行它,不需要PreparedStatement

    String getCreateTableSql(int columns) {
      StringBuilder sql = new StringBuilder("CREATE TABLE IF NOT EXISTS itemset (");
      for (int i = 0; i < columns; i++) {
        if (i > 0) {
          sql.append(", ");
        }
        sql.append("item").append(i + 1).append(" TINYINT(10)");
      }
      sql.append(")");
      return sql.toString();
    }
    

    对于 4 列,这将输出:

    CREATE TABLE IF NOT EXISTS itemset (item1 TINYINT(10), item2 TINYINT(10), item3 TINYINT(10), item4 TINYINT(10))

    【讨论】:

    • 是的,简单的声明是有效的,但我想尝试准备声明。无论如何,谢谢
    猜你喜欢
    • 2017-03-02
    • 1970-01-01
    • 2011-08-12
    • 1970-01-01
    • 1970-01-01
    • 2017-10-20
    • 2013-12-06
    • 2017-09-10
    • 1970-01-01
    相关资源
    最近更新 更多