4

This is driving me nuts... What am I doing wrong here?

ArrayList<String> toAdd = new ArrayList<String>();
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();
}

Results in...

02:59:12,885 ERROR [STDERR] com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ''password' varchar(100)' at line 1

but...

ArrayList<String> toAdd = new ArrayList<String>();
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();
}

works perfectly... So does directly entering the text directly into the MySQL command line client.

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

What am I doing wrong?

6 Answers 6

11

The MySQL manual clearly says that ? (parameter markers) are for binding data values only, not for column names.

Parameter markers can be used only where data values should appear, not for SQL keywords, identifiers, and so forth.

So you will have to use your second approach.

Sign up to request clarification or add additional context in comments.

2 Comments

Ahh, thanks. I'd give you an upvote, but it won't let me yet. ;)
This same restriction is found in Oracle, SQL Server, DB2, Teradata, and every other relational database I've worked with. The restriction has to do with how a SQL statement is processed by the optimizer. The bind values are supplied too late in the processing, when the query plan is executed. The keywords need to be available earlier, for the syntax check. And tables, columns, functions, etc. have to identified during the semantics check, before the query plan is developed/chosen. The bind values aren't supplied until the query plan is executed.
1

Placeholders in JDBC are for data, not for table, column, view or function names. And for good reason. The DB schema of an application is static most of the time and only changes rarely. There are no benefits making them dynamic.

1 Comment

Yes, bind parameters/placeholders can only be used for values. Not for identitfiers or keywords. The limitation is primarily due to the SQL optimizer (how a SQL statement is processed on the database). The limitation is not a specific to JDBC. (The reason given in this answer is specious.)
1

Prepared statements need to define a fixed structure so they can be precompiled. That means you can have variable values, but never variable table names, column names, function names etc.

Comments

1

When using a prepared statement, your parameter is treated similarily to a string literal. As a result, your statement is equivalent to "ALTER TABLE testTable ADD \'"+s+"\' varchar(100)". Notice the single quotations around the field name in the error message.

I would suggest building a literal statement in this case, and not attempting to used a prepared statement.

Comments

-1

You cannot submit an ALTER TABLE statement using parameters like this.

I guess it is not permissible to execute DDL statements in Java PreparedStatement.

Comments

-1

Try using the following

pStmt.executeUpdate();

pStmt.close();

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.