Java PreparedStatement在execute()上抱怨SQL语法

这让我疯了……我在这里做错了什么?

ArrayList toAdd = new ArrayList(); toAdd.add("password"); try{ PreparedStatement pStmt = conn.prepareStatement("ALTER TABLE testTable ADD ? varchar(100)"); for (String s : toAdd) { pStmt.setString(1, s); pStmt.execute(); } } catch (SQLException e) { e.printStackTrace(); } 

结果是…

02:59:12,885 ERROR [STDERR] com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException:SQL语法中有错误; 查看与您的MySQL服务器版本对应的手册,以便在第1行的”password’varchar(100)’附近使用正确的语法

但…

 ArrayList toAdd = new ArrayList(); toAdd.add("password"); try{ Statement stmt = conn.prepareStatement(); for (String s : toAdd) { stmt.execute("ALTER TABLE testTable ADD "+s+" varchar(100)"); } } catch (SQLException e) { e.printStackTrace(); } 

完美的工作……直接将文本直接输入MySQL命令行客户端。

 mysql> alter table testTable add stringGoesHere varchar(100); Query OK, 1 row affected (0.23 sec) Records: 1 Duplicates: 0 Warnings: 0 

我究竟做错了什么?

MySQL手册清楚地说明了? (参数标记)仅用于绑定数据值,不用于列名。

参数标记只能用于应出现数据值的位置,而不能用于SQL关键字,标识符等。

所以你必须使用你的第二种方法。

JDBC中的占位符用于数据,而不是表,列,视图或函数名称。 并且有充分的理由。 应用程序的数据库模式大部分时间都是静态的,只是很少更改。 没有任何好处使他们充满活力。

准备好的语句需要定义一个固定的结构,以便可以对它们进行预编译。 这意味着你可以拥有变量 ,但永远不会有变量表名,列名,函数名等。

使用预准备语句时,您的参数将被视为字符串文字。 因此,您的语句相当于“ALTER TABLE testTable ADD \’”+ s +“\’varchar(100)”。 请注意错误消息中字段名称周围的单引号。

我建议在这种情况下构建一个文字语句,而不是试图使用准备好的语句。

您不能使用这样的参数提交ALTER TABLE语句。

我想在Java PreparedStatement中执行DDL语句是不允许的。

尝试使用以下内容

pStmt.executeUpdate();

pStmt.close();