PreparedStatement executing successfully in oracle but throwing exception in Microsoft SQL - java

I have this below query that I execute using java PreparedStatement:
String dml=insert into users(name, addr, city, sex, dob) values(?,?,?,?,?);
PreparedStatement stmt = conn.prepareStatement(dml);
stmt.setString(1,"abcd");
stmt.setString(2,"def");
stmt.setString(3,"ghij");
stmt.setString(4,"m");
stmt.setString(5,"1-Jan-1987");
stmt.executeQuery();
It executes successfully when the database is Oracle, but when the database is Microsoft SQL, then it throws an exception "java.sql.SQLException: The executeQuery method must return a result set". Could someone please tell what is the issue here. Why is the same query executing successfully in oracle but not in microsft sql?

The answer is in the message - ExecuteQuery requires a result set. Use executeUpdate instead.
From the above Link:
boolean execute() Executes the SQL statement in this PreparedStatement object, which may be any kind of SQL statement.
ResultSet executeQuery() Executes the SQL query in this PreparedStatement object and returns the ResultSet object generated by the query.
int executeUpdate() Executes the SQL statement in this PreparedStatement object, which must be an SQL INSERT, UPDATE or DELETE statement; or an SQL statement that returns nothing, such as a DDL statement.
the fact that it works on oracle is probably just a side effect which you've discovered cannot be relied upon.

If you're performing an INSERT/UPDATE statement, you should be calling stmt.executeUpdate() rather than stmt.executeQuery(). I imagine there's a difference (though I don't know exactly what) between the Oracle and SQL Server drivers you're using that means that one works and the other one doesn't.

try using the method executeUpdate instead of executeQuery.
since the query at hand is not a select-query, it fails. executeQuery is for select-queries, executeUpdate is for insert, delete and update-queries.

There is the problem on stmt.executeQuery();
executeQuery() is used for SELECT sql operation
executeUpdate() is used for INSERT, UPDATE and DELETE sql operation.
your query is for INSERT operation thus please use stmt.executeUpdate();

This depends upon driver that are using and underlying implementation of executeQuery() method. While using Java Prepared statement the underlying implementation allow this but the driver of SQL server doesnot allow this.
Try to use correct method to execute insert statement like executeUpdate().
go trough this links:-
Sql server:- http://msdn.microsoft.com/en-us/library/ms378540%28v=sql.90%29.aspx
Oracle:- http://docs.oracle.com/javase/1.4.2/docs/guide/jdbc/getstart/statement.html

use stmt.execute(); instead of stmt.executeQuery();
stmt.execute(); or executeUpdate(); for INSERT, UPDATE, DELETE (etc.)
stmt.executeQuery(); for SELECT

Related

java.sql.SQLSyntaxErrorException when inserting into MySQL database using PreparedStatement [duplicate]

I'm trying to execute a query using a PreparedStatement in Java.
I am getting error number 1064 when I try to execute my query (syntax error).
I have tested this in MySQL query browser with substituted values which works fine.
What's wrong with my code?
Here's the relevant code:
String query = "select MemberID, MemberName from members where MemberID = ? or MemberName = ?";
Connection conn = DriverManager.getConnection(DATABASE_URL, USERNAME, PASSWORD);
PreparedStatement s = conn.prepareStatement(query);
s.setInt(1, 2);
s.setString(2, "zen");
ResultSet rs = s.executeQuery(query);
Here's the exception I'm getting:
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 '? or MemberName
= ?' at line 1
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 '? or MemberName = ?' at line 1
MySQL doesn't understand the meaning of ? in the SQL query. It's indeed invalid SQL syntax. So somehow it's not been replaced by PreparedStatement. And guess what?
PreparedStatement s = conn.prepareStatement(query);
s.setInt(1, intValue);
s.setString(2, strValue);
rs = s.executeQuery(query); // Fail!
You're overridding the prepared query with the original query! You need to call the argumentless PreparedStatement#executeQuery() method instead of Statement#executeQuery(String).
PreparedStatement s = conn.prepareStatement(query);
s.setInt(1, intValue);
s.setString(2, strValue);
rs = s.executeQuery(); // OK!
Unrelated to the problem, your code is leaking resources. The DB will run out of them after several hours and your application will crash. To fix this, you need to follow the JDBC idiom of closing Connection, Statement and ResultSet in the finally block of the try block where they're been acquired. Check the JDBC basic tutorial for more detail.
If you look at the javadocs for Statement (the superclass of PreparedStatement), the method docs for executeQuery(String) and executeUpdate(String) say this:
Note: This method cannot be called on a PreparedStatement or CallableStatement.
That's what you are doing here: calling executeQuery(String) from Statement on a PreparedStatement object.
Now since the javadocs say that you "cannot" do this, actual behavior you get is unspecified ... and probably JDBC driver dependent. In this case, it appears that the MySQL driver you are using is interpreting this to mean that you are doing the update as a non-prepared statement, so that the ? tokens are NOT interpreted as parameter placeholder. That leads the server-side SQL parser to say "syntax error".
(It would be easier for programmers if a different unchecked exception was thrown by the MySQL driver if you did this; for example UnsupportedOperationException. However, the standard JDBC javadocs don't say what should happen in this situation. It is up to the vendor what their drivers will do.)

JDBC doesn't seem to want to call DELETE PreparedStatement when batched for MySQL

When I run the code in non-batch mode it works:
PreparedStatement preparedStatement = connection.prepareStatement(
"DELETE FROM myTable WHERE id=58");
preparedStatement.execute();
However as soon as I try to run it in batch mode:
PreparedStatement preparedStatement = connection.prepareStatement(
"DELETE FROM myTable WHERE id=58");
preparedStatement.executeBatch();
It will no longer delete the entry from the table. All my INSERTS work perfectly well with executeBatch, in fact everything so far except the DELETE command. It doesn't come back with any kind of error, it just seems to ignore the command and skip over it. And if I inspect the number of columns affected by looking at the int[] returned it's empty (int[].length = 0).
Update: I don't believe it's a permission issue because the user account has full root privileges and access to all commands. And if it was a permission issue then it shouldn't work in non-batch mode.
The issue was that for the delete SQL statement for whatever reason I forgot to add the following line:
preparedStatement.addBatch();
Omitting this line means the PreparedStatement was never added to the batch and hence never executed. There are of course no warnings or errors because the SQL statement is never executed, it's just omitted. As there were other SQL batch PreparedStatement in the batch there was no need for an empty batch exception to be thrown (some drivers will throw an exception but this is not guaranteed so don't rely on it).
Therefore the correct code would be:
PreparedStatement preparedStatement = connection.prepareStatement(
"DELETE FROM myTable WHERE id=58");
preparedStatement.addBatch();
preparedStatement.executeBatch();
Now as pointed in a comment you would normally not want to execute a single SQL command with batching, the reason this was done was to isolate the issue to the specific SQL command.

Execute a PL/SQL procedure using Java code

I would like to execute PL/SQL procedure using Java code. I've tried this so far :
Statement myStmt = null;
myStmt = conn.createStatement();
myStmt.executeQuery("EXECUTE ProjetIRSTEA.detectionX");
And I get the following error message:
java.sql.SQLSyntaxErrorException: ORA-00900: invalid SQL statement
You have to use the CallableStatement class to execute Stored Procedures.
Please, check this sample published by Oracle to see how to use this class:
https://docs.oracle.com/cd/A84870_01/doc/java.816/a81354/samapp2.htm
Try:
myStmt.executeUpdate("BEGIN ProjetIRSTEA.detectionX; END");
You can also use a method of calling stored procedures defined by the JDBC standard, using CallableStatement Interface:
CallableStatement myCall = connection.prepareCall("{call ProjetIRSTEA.detectionX()}")
myCall.executeUpdate();
On Oracle, you can use either a CallableStatement (as explained above) or just issue a normal sql query using a Statement or PreparedStatement (the former method is preferred though) .
String sql = " select ProjetIRSTEA.detectionX() from dual";
PreparedStatement stmt = conn.prepareStatement(sql);
stmt.execute();
Note that you have to reference the system table dual in your select statement.

getGeneratedKeys() after PreparedStatement.executeBatch()

I want to INSERT several rows using a PreparedStatement:
ps = con.prepareStatement(query,PreparedStatement.RETURN_GENERATED_KEYS);
for(Element e:listOfElements){
ps.setString(1,this.col_val_1);
ps.setString(2,this.col_val_2);
ps.setInt(3,this.col_val_3);
ps.addBatch();
}
ps.executeBatch();
ResultSet rs = ps.getGeneratedKeys();
At this point, whent I expect to get the PK's generated for each INSERT, I get this SQLServerException:
com.microsoft.sqlserver.jdbc.SQLServerException: The statement must be executed before any results can be obtained.
I expected to get a ResultSet with one row for each insert performed, so I could get each PK generated.
Am I expecting wrong? Am I doing something wrong? Can it be done in a different way using batch execution?
Support for getGeneratedKeys() on batch execution is implementation defined according to the JDBC spec. Most likely the SQL Server driver does not support it for batch execution.
I tried to look for an explicit statement on the Microsoft site, but couldn't find it. This old (2007) forum post on MSDN does state that it isn't supported: http://social.msdn.microsoft.com/Forums/en-US/sqldataaccess/thread/6cbf5eea-e5b9-4519-8e86-f4b65ce3f8e1

Can not issue data manipulation statements with executeQuery() [duplicate]

This question already has answers here:
Cannot issue data manipulation statements with executeQuery()
(11 answers)
Closed 7 years ago.
I use com.mysql.jdbc.Driver
I need insert and get id.
My query:
INSERT INTO Sessions(id_user) VALUES(1);
SELECT LAST_INSERT_ID() FROM Sessions LIMIT 1;
error -
Can not issue data manipulation
statements with executeQuery()
How insert and get id?
You will need to use the executeUpdate() method to execute the INSERT statement, while you'll need to use the executeQuery() method to execute the SELECT statement. This is due to the requirements imposed by the JDBC specification on their usages:
From the Java API documentation for Statement.executeQuery():
Executes the given SQL statement, which returns a single ResultSet
object.
Parameters:
sql - an SQL statement to be sent to the database, typically a static SQL SELECT statement
and from the Java API documentation for Statement.executeUpdate():
Executes the given SQL statement, which may be an INSERT, UPDATE, or DELETE statement or an SQL statement that returns nothing, such as an SQL DDL statement.
Parameters:
sql - an SQL Data Manipulation Language (DML) statement, such as INSERT, UPDATE or DELETE; or an SQL statement that returns nothing, such as a DDL statement.
Your code (pseudo-code posted here) should appear as:
statement.executeUpdate("INSERT INTO Sessions(id_user) VALUES(1)"); // DML operation
statement.executeQuery("SELECT LAST_INSERT_ID()"); // SELECT operation
And of course, the MySQL documentation demonstrates how to perform the same activity for AUTO_INCREMENT columns, which is apparently what you need.
If you need to execute both of them together in the same transaction, by submitting the statements in one string with a semi-colon separating them like the following:
statement.execute("INSERT INTO Sessions(id_user) VALUES(1); SELECT LAST_INSERT_ID() FROM Sessions LIMIT 1;");
then you'll need to use the execute() method. Note, that this depends on the support offered by the Database and the JDBC driver for batching statements together in a single execute(). This is supported in Sybase and MSSQL Server, but I do not think it is supported in MySQL.
may be you are using executeQuery() but to manipulate data you actually need executeUpdate() rather than executeQuery()
Connection connection = null;
PreparedStatement preparedStatement = null;
ResultSet generatedKeys = null;
try {
connection = m_Connection;
preparedStatement = (PreparedStatement) connection.prepareStatement(qString, Statement.RETURN_GENERATED_KEYS);
// ...
int affectedRows = preparedStatement.executeUpdate();
if (affectedRows == 0) {
throw new SQLException("Creating user failed, no rows affected.");
}
generatedKeys = preparedStatement.getGeneratedKeys();
int id = -1;
if (generatedKeys.next()) {
id = generatedKeys.getInt(1);
id = -1;
} else {
throw new SQLException("Creating user failed, no generated key obtained.");
}
} finally {
}
For non-select SQL statements you use ExecuteNonQuery();
To get the last inserted id, you can do this SQL statement.
SELECT LAST_INSERT_ID() AS last_id
Although there's probably an java wrapper for that select statement.
Links:
http://dev.mysql.com/doc/refman/5.0/en/getting-unique-id.html
http://wiki.bibalex.org/JavaDoc/org/bibalex/daf/handlers/dbhandler/DBConnection.html

Categories