2

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

这是代码:

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 > number of parameters, which is 1)

它发生在第二次迭代期间的 setString 行中

4

4 回答 4

2

尝试移动

up1 = con.prepareStatement(sql); 

System.out.println(sql);
于 2012-06-06T21:05:42.097 回答
1

String您要修复的第一件事是,当您想更改它时,请不要使用实例。String实例是不可变的,当您修改已经创建的时String,会创建新的修改实例并且它不是免费的。您应该为此使用StringBuilder具有允许修改它而无需创建新实例的实例方法。我建议您StringBuilder在修改时始终使用String. 其次,你打电话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();

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


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

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();
于 2012-06-06T21:08:55.590 回答
1

虽然我没有验证,但我相信 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();
于 2012-06-06T21:16:26.043 回答
0

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

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

当仅给出列数时,只需创建 CREATE TABLE 语句(StringBuilder如其他人建议的那样使用 a )并使用 plain 执行它Statement,不需要 a 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))

于 2012-06-06T21:16:06.207 回答