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?
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.
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.
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.
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.
You cannot submit an ALTER TABLE statement using parameters like this.
I guess it is not permissible to execute DDL statements in Java PreparedStatement.
Try using the following
pStmt.executeUpdate();
pStmt.close();
Related
There is a select query that I am executing with DB2 JDBC. I am using Prepared Statement to pass in the value for the parameter. The column length of that parameter in the database is 12 so everything works fine until the length of the value is 12 and then it fails. Throws an exception with the error message as in the title. I did some searching and found an explanation in the following link http://www-01.ibm.com/support/docview.wss?uid=swg21319477 and the resolution mentioned in there is as below
Resolving the problem
Add additional client side validation code to prevents queries, with values that are larger than the allowed maximum length to be ran.
I don't want to do this. Why wouldn't the query just return back with no results. Any idea how do I go about this?
EDIT
String sql = "select student_id, student_name from student where student_id = ?";
try (Connection connection = DBUtils.GetConnection)
{
try (PreparedStatement statement = connection.prepareStatement(sql))
{
statement.setString(1, student_id);
ResultSet result = statement.executeQuery();
while (result.next())
{
//...
}
}
}
Even though I do not recommend doing it: We had a similar problem and found that - at least in our case -, if you really want that empty result, you can use a native SQL query instead of the prepared statement. Apparently, it is the argument binding for the prepared statement which runs into the argument validation. The native query (which you would have manually constructed using your arguments) seemed to sidestep this validation, and just returned an empty result.
(For completeness' sake: If really manually constructing your SQL query from given arguments, be sure to know what you are doing, validate your arguments, and specifically beware of SQL injection.)
The correct answer here would be what #Gaius Gracchus offers up as an alternative suggestion in his comment to #Hans's answer. You try/catch the SQLException, gather its SQL State (always better than an SQL Code), and handle/throw a custom exception to indicate invalid input to the client. An empty result set (even though that is what the OP desires) is not accurate. The only other real alternative is to increase the size of the column or procedural input/input-output (not likely).
try {
// sql bind or execute
}
catch (SQLException e) {
String sqlState = e.getSQLState();
if (sqlState != null && sqlState.equals("22001")) {
throw new CustomException("Invalid input, etc");
}
throw e;
}
I am trying to insert the data below into a table that has the columns ID[autoNumber], type[text], to[text], from[text], message[text] and attachmentLoc[text]
So the autonumber is generated I insert them supplying the column names. When it runs the console prints out:
java.sql.SQLException: [Microsoft][ODBC Microsoft Access Driver] Syntax error in INSERT INTO statement.
at sun.jdbc.odbc.JdbcOdbc.createSQLException(JdbcOdbc.java:6957)
at sun.jdbc.odbc.JdbcOdbc.standardError(JdbcOdbc.java:7114)
at sun.jdbc.odbc.JdbcOdbc.SQLExecute(JdbcOdbc.java:3149)
at sun.jdbc.odbc.JdbcOdbcPreparedStatement.execute(JdbcOdbcPreparedStatement.java:216)
at sun.jdbc.odbc.JdbcOdbcPreparedStatement.executeUpdate(JdbcOdbcPreparedStatement.java:138)
at MultiEchoServer.saveMessage(MultiEchoServer.java:147)
at ClientHandler.run(MultiEchoServer.java:409)
The code that is bringing the error is :
try
{
String sql = "INSERT INTO Messages (type, to, from, message, attachmentLoc) VALUES(?,?,?,?,?)";
PreparedStatement stmt = database.prepareStatement(sql);
stmt.setString(1, message.getType());
stmt.setString(2, message.getTo());
stmt.setString(3, message.getFrom());
stmt.setString(4, message.getMessage());
stmt.setString(5, attachmentLoc);
stmt.executeUpdate();
}
catch (SQLException e)
{
System.out.println("Could not perform statement");
e.printStackTrace();
}
Thanks for your help
You don't state what database engine you're using, but a number of the column names (as well as the table name) are likely candidates for reserved words. The very most obvious is from.
You will need to write those identifiers in identifier quotes which are generally either the backtick character (`) or the characters [ and ] (depending on engine):
INSERT INTO `Messages` (`type`, `to`, `from`, `message`, `attachmentLoc`)
VALUES (?,?,?,?,?);
or
INSERT INTO [Messages] ([type], [to], [from], [message], [attachmentLoc])
VALUES (?,?,?,?,?);
The quoting is only required around the identifiers that are reserved words but using it around all identifiers will not hurt. Also, no reason not to include the space after VALUES and the semi-colon at the end of the statement (although most engines don't need either).
You need valid syntax for the INSERT statement. SQL does not understand the question mark.
Perhaps, you want one of the following:
'?'
NULL
''
Or some other value.
So, assuming the columns accept NULL values, you could use:
VALUES(NULL, NULL, NULL, NULL, NULL)
From is a reserved word, after this was changed to messageFrom it allowed the insertion to the database.
Currently i'm writing a JDBC application to manage a MySQL database. I have the delete, insert and select methods functioning with the correct queries. I'm having trouble with the Update method. When using using the following code I receive a MySQL error:
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 "",Street",Town",City",PostCode",Age",email",RunningFee'false'Where PID=" at line 1...
private void updateData()
{
Connection con;
try
{
Class.forName("com.mysql.jdbc.Driver");
con = DriverManager.getConnection(
"jdbc:mysql://localhost/snr","root","");
String sql = "Update participant Set password='"+txtpassword.getText()+"'," +
"lastName='"+txtlastName.getText()+"',firstName='"+
txtfirstName.getText()+"',HouseNumber'"+txtHouseNumber.getText()+"',Street'"+txtStreet.getText()+"',Town'"+txtTown.getText()+"',City'"+txtCity.getText()+"',PostCode'"+txtPostCode.getText()+"',Age'"+txtAge.getText()+"',email'"+txtemail.getText()+"',RunningFee'"+cbRunningFee.isSelected()+"' Where PID='"+txtPID.getText()+"'";
Statement statement = con.createStatement();
statement.execute(sql);
createMessageBox("Updated Successfully");
clearControls();
}
catch(Exception e)
{
createMessageBox(e.getMessage());
}
}
Is there something wrong with my SQL query?
Yes, your query is wrong. You're missing = on a great big bunch of set column/value pairs.
(And please consider using prepared statements and bind variables, SQL injection is just not something you want to be open to.)
Yes there is something wrong with the query. Your way of building query is vulnerable to SQL Injection. Use Parameterized Queries instead of concatenating text like that.
Read this article: Preventing SQL Injection in Java
Not only is your query incorrect, but it may also open you to SQL Interjection Attacks.
You need to parameterize your query by replacing the pasted-in values with question marks, preparing the statement, and executing it. See the tutorial that I linked.
Finally, storing a password as plain text is a very, very bad idea.
String sql = "UPDATE participant SET "+
"password=?, lastName=?, firstName=?, HouseNumber=?, Street=?, Town=?, "+
"City=?,PostCode?,Age=?,email=?,RunningFee=? "+
"WHERE PID=?";
PreparedStatement upd = con.prepareStatement(sql);
upd.setString(1, txtpassword.getText());
upd.setString(2, txtlastName.getText());
// ... and so on
upd.executeUpdate();
con.commit();
You are forgetting some = in your query.
Try
String sql = "Update participant Set password='"+txtpassword.getText()+"'," +
"lastName='"+txtlastName.getText()+"',firstName='"+
txtfirstName.getText()+"',HouseNumber='"+txtHouseNumber.getText()+"',Street='"+
txtStreet.getText()+"',Town='"+txtTown.getText()+"',City='"+txtCity.getText()+
"',PostCode='"+txtPostCode.getText()+"',Age='"+txtAge.getText()+"',email='"+
txtemail.getText()+"',RunningFee='"+cbRunningFee.isSelected()+
"' Where PID='"+txtPID.getText()+"'";
The error 'you have an error in your SQL syntax' is from the sql server and indicates that yes, you do have an error in your query. In these cases I often find it useful to print the constructed query itself, just to check that it is being constructed correctly.
In your case I believe the problem is that you are missing a bunch of "="s, you also probably need to escape your single quotes in the java so they are passed through correctly (replace ' with \').
This question already has answers here:
java.sql.SQLException: Column count doesn't match value count at row 1
(3 answers)
Closed 6 years ago.
try {
Statement stmt = con.createStatement();
stmt.executeUpdate("INSERT into emailacc(fname,lname,uname,mail,passwd,passwd2,date,month,year) values('"+fname+","+lname+","+uname+","+mail+","+passwd+","+passwd2+","+date+","+selectMonth+","+year+"')");
out.println("<h3><font color='green'>Information Added Successfully.</font><br> You Are a registered User now.</h3><br>");
con.close();
} catch(Exception e) {
out.println("Exception caught : "+e);
}
Why is it happening?
Last time I did the same but it didn't happen, whats wrong with it?
Well to start with what's wrong with it is that you're including the values directly into your SQL. Don't do that. Ever. Use a parameterized SQL statement via PreparedStatement, and set the parameter values appropriately. That way you don't need to worry about SQL injection attacks, and it'll also be a lot easier to look at what the actual SQL is, without worrying about where the values come from (or rather, separating those two concerns).
I suspect the immediate problem is that you're not quoting any values, so you've got a SQL statement like a longer version of:
INSERT into Foo(name) VALUES (jon)
rather than
INSERT into Foo(name) VALUES ('jon')
... but using parameterized SQL will fix this anyway, so please don't just change the SQL to include single quotes everywhere.
Is because you are omitting single quotes, for avoid this mistakes my recommendation is to use PreraredStatement, also in order to proper close connection it mus be in a finally block , you code must look at this:
try {
PreparedStatement stmt = con.prepareStatement("INSERT into emailacc(fname,lname,uname,mail,passwd,passwd2,date,month,year) values(?,?,?,?,?,?,?,?,?)");
stmt.setString(1,fname);
stmt.setString(2,lname);
stmt.setString(3,uname);
stmt.setString(4,mail);
stmt.setString(5,passwd);
stmt.setString(6,passwd2);
stmt.setDate(7,date); //you need convert your date to java.sql.Date if 'date' field of database is of type date. If not setString is fine
stmt.setInt(8,selectMonth);
stmt.setInt(9,year);
stmt.executeUpdate();
out.println("<h3><font color='green'>Information Added Successfully.</font><br> You Are a registered User now.</h3><br>");
} catch (Exception e) {
con.rollback();
out.println("Exception caught : " + e);
} finally {
if (con != null) {
try {
con.close();
} catch(SQLException ex){
//DO NOTHING
}
}
}
You can learn more of PreparedStatemt in:
http://download.oracle.com/javase/tutorial/jdbc/basics/prepared.html
A final note: PreparedStament are more efficent thant Statement and avoid the SQL Injection hack so PrepararedStatement is more secure. Try use always a PreparedStatement
Your insert statement is missing quotes between the string insert statement should be:
INSERT into emailacc(fname,lname,uname,mail,passwd,passwd2,date,month,year) values('"+fname+"','"+lname+"','"+uname+"','"+mail+"','"+passwd+"','"+passwd2+"',"+date+","+selectMonth+","+year+")");
every column varchar or text should be between single quotes also double check your date format you might have to use the to_date function : to_date(,'DD-MM-YYYY') just a sample
I'm trying to execute this script through JDBC (it's SQL Server):
DECLARE #var VARCHAR(10)
SET #var = "test"
INSERT INTO foo (name) VALUES (#var)
It's just an example, in my business case I have a big collection of SQL statements in one script.
I'm trying this:
final Statement stmt = connection.createStatement();
for (String sql : lines) {
stmt.executeUpdate(sql);
}
stmt.close();
SQL Server is saying on the second line:
java.sql.SQLException: Must declare the scalar variable "#var".
Looks like I'm doing something wrong...
You're executing it one line at a time, so of course the second line fails as it depends on the first line. Why not execute it all at once?...