ResultSet is from UPDATE. No Data - java

The problem occurs when executeQuery function runs, the sql statement is work correctly and gives correct results when it is runned on the sql editor. When it is runned on jdbc it is not executed. The connection accepts multi queries.
String query = "set #countOfLectureGrade = (SELECT Count(goc.Affect) FROM GradeOfCourse goc WHERE goc.LectureID = ?);"
+ "SELECT u.SchoolID, u.Name, u.Surname, u.Role, u.Email, "
+ "CASE WHEN #countOfLecture = 0 then 0 "
+ "ELSE AVG(0.01 * goc.Affect * gos.Grade) "
+ "END AS Average "
+ "FROM GradeOfCourse goc, GradeOfStudent gos, User u, CourseOfStudent cos "
+ "WHERE "
+ "(gos.CourseGradeID = goc.GradeID AND u.SchoolID = gos.StudentID AND goc.LectureID = ?) "
+ "OR (u.SchoolID = cos.SchoolID AND cos.LectureID = ? AND #countOfLectureGrade = 0) "
+ "GROUP BY u.SchoolID;";
try {
connection = super.getConnection();
PreparedStatement sqlStatement = connection.prepareStatement(query);
sqlStatement.setInt(1, lectureID);
sqlStatement.setInt(2, lectureID);
sqlStatement.setInt(3, lectureID);
ResultSet resultSet = sqlStatement.executeQuery();
java.sql.SQLException: ResultSet is from UPDATE. No Data.

This is not possible, you have to separate your queries, of for the best solution you can use procedures or function.
Procedure should take lectureID
Return your result, in your case it should multiples valus, you can read How to retrieve multiple rows from stored procedure in mysql? to know how to use procedure return multiple values

I am not familiar with JDBC but a quick search suggests you should use execute rather than executeQuery.
execute: Returns true if the first object that the query returns is a
ResultSet object. Use this method if the query could return one or
more ResultSet objects. Retrieve the ResultSet objects returned from
the query by repeatedly calling Statement.getResultSet.
https://docs.oracle.com/javase/tutorial/jdbc/basics/processingsqlstatements.html#executing_queries

Have a look at the following documentation which explains to use execute() instead of executeQuery() and then fire a getResultSet() on the Result set that you get.
The whole approach is to change your query into a Stored procedure and invoke the same through a CallableStatement.
Documentation suggests:
Although CallableStatement supports calling any of the Statement execute methods (executeUpdate(), executeQuery() or execute()), the most flexible method to call is execute(), as you do not need to know ahead of time if the stored procedure returns result sets.
Hope this helps!

Related

Returning clause fails (postgres 9.3, jdbc)

I have looked at several link to retrieve the id with an insert using java, and I thought I would use the RETURNING clause.
my code:
Connection c = DriverManager.getConnection("jdbc:postgresql://localhost:5432/testdb?ssl=true&sslfactory=org.postgresql.ssl.NonValidatingFactory", "postgres","root");
String sql = "INSERT INTO main (nom_fichier, adate, mdate, cdate, size, chunknumber)"
+ " VALUES ('test',450,450,450,450,5)"
+ " Returning id"
+ ";";
Statement stmt = c.createStatement();
int rowNumber = stmt.executeUpdate(sql);
But I get this error:
Exception in thread "main" org.postgresql.util.PSQLException: a result was returned when none was expected.
at org.postgresql.jdbc2.AbstractJdbc2Statement.executeUpdate(AbstractJdbc2Statement.java:339)
at fr.infotel.postgre.TestPostgre.main(TestPostgre.java:25)
I also tried to use the Statement.RETURN_GENERATED_KEYS (withouth Returning clause) without success (I had nothing in the result set).
First Question: I would like to make the RETURNING statement work, as my request works in psql
Second Question: If the first is not possible, how can I have the same result
I am using postgres 9.3 with the postgres9.3.jdbc3 jar.
Thanks for your help.
Use ResultSet object instead of rowNumber
ResultSet resultSet = stmt.executeQuery(sql);
your query result now in resultSet variable.

Java code not executing. It is getting stuck at CallableStatement cs = con.prepareCall(plsql);

It seems like callable statement is not getting executed in the following code.
Connection con = DBConnection.getConnection(schema,uName,pwd);
String plsql =" " +
"BEGIN " +
" for crec in (select distinct filename from flex_template) loop " +
" Update vfs3 set created=sysdate where name =crec.filename;" +
" Update vfs3_data set data =(select data from vfs3_data#uktest02 where file_id in (select file_id from vfs3#uktest02 where name=crec.filename )) where file_id in (select file_id from vfs3 where name=crec.filename) ;" +
" end loop;" +
"END;" ;
CallableStatement cs = con.prepareCall(plsql);
System.out.println("After plsql prpare call");
cs.execute();
con.commit();
System.out.println("File updated successfully");
cs.close();
con.close();
I want to run the plsql begin end block in oracle database. Could anyone please advise how this can be accomplished..
You misunderstand what CallableStatement allows you to do.
It's designed to call existing stored procedures, not to allow you to execute ad-hoc blocks of PL/SQL code.
Define your PL/SQL as a stored procedure in the database, then use CallableStatement to execute that stored procedure (optionally passing in any parameters you need).
Check the javadoc for CallableStatement for details about the exact syntax requirements for the call.

JDBC exception "Operation not allowed after ResultSet closed" when iterating over ResultSet

I have a problem with this code:
ResultSet dane = statement.executeQuery("SELECT * FROM ProWarns WHERE blahblah = '" + cel + "'");
while (dane.next()) {
// some code (only get some string from result)
if (TimeEnd <= EndTime) {
statement.executeUpdate(
"DELETE FROM ProWarns WHERE id = '" + id + "'"); //and error
statement.executeUpdate(
"UPDATE ProWarnsPlayers SET num = '" + NewV + "'" WHERE Pl = '"+ tar + "'");
}
}
Error: java.sql.SQLException: Operation not allowed after ResultSet closed. Where is the bug and how can I fix it?
PS:
I am including a Pastebin of my DB class, in case its helpful.
A Statement object caches its result set, so when you execute the additional operations in your for loop the original result set gets 'reset'. Which leads to the error that is happening, when you call dane.next. From the Javadoc:
By default, only one ResultSet object per Statement object can be open
at the same time. Therefore, if the reading of one ResultSet object is
interleaved with the reading of another, each must have been generated
by different Statement objects. All execution methods in the Statement
interface implicitly close a statment's current ResultSet object if an
open one exists.
Options? Use another Statement object to execute the inner queries.

SQL queries through Java, "Illegal operation on empty result set"

I'm making a db call as follows:
String sqlAlert = "SELECT * FROM demotable where demo_no ='"
+rsDemo.getString("demo_no") + "'";
ResultSet rsAlert = db.GetSQL(sqlAlert);
if (rsAlert.next()) {
String newAlert = rsAlert.getString("cust3")+"1";
String newAlertSql = "UPDATE demotable SET cust3 = '" + newAlert + "' where demo_no='" + rsDemo.getString("demo_no") + "'";
System.out.println("Update alert msg: " + newAlertSql);
db.RunSQL(newAlertSql);
} else {
System.out.println("empty result. Demo_no = "+rsDemo.getString("demo_no"));
String sqlAlertinsert = "INSERT INTO demotable VALUES('" + rsDemo.getString("demo_no") + "','','','','','<unotes></unotes>')";
db.RunSQL(sqlAlertinsert);
System.out.println("insert demo done");
String sqlAlert2 = "SELECT * FROM demotable where demo_no ='"rsDemo.getString("demo_no") + "'";
ResultSet rsAlert2 = db.GetSQL(sqlAlert2);
if (rsAlert2.next()) {
String newAlert = rsAlert2.getString("cust3")+"1";
String newAlertSql = "UPDATE demotable SET cust3 = '" + newAlert+ "' where demo_no='" + rsDemo.getString("demo_no") + "'";
System.out.println("Update alert msg: " + newAlertSql);
db.RunSQL(newAlertSql);
}
rsAlert2.close();
}
rsAlert.close();
rs.close();
I am trying to insert rows into demographiccust if rsAlert returns an empty set and then access values from it. But my code returns this exception "Illegal operation on empty result set" around "if (rsAlert2.next()) { ". Why does it return an empty set even after inserting values into the table? Please help. Thank you.
It may be because of the open cursor. You must close your first Statement, prior trying the second. ResultSet is a connected thing, when you close the Statement it get closed too. I can't see the implementation of your db.RunSQL() and db.GetSQL() methods.
However, I am having the suggestion on how you should do it, in the first place. Here you go,
Update it without querying the database
Check how many rows updated. If none, then step 3, otherwise completed
Insert the record with the correct values in the first place. No need to update it after inserting.
Tips:
Try using PreparedStatement, instead
Try to stick with Java Naming Convention
Try using meaningful names, i.e. for example your method db.GetSQL() is not returning an SQL, but contrarily asking one, and in fact returning a ResultSet.
Never return a ResultSet. This may lead to bloated code and a lot of open cursors. Don't make the user of your method to close it. Close it yourself in your method where you are performing any database query, and return the result as a bean or a list of beans.
It's just a guess, but because you are interpolating rsDemo.getString("demo_no") directly into the SQL, you may be passing an SQL statement that isn't what you want. Try using the parameter binding api.

Cannot issue data manipulation statements with executeQuery()

In MySQL I have two tables, tableA and tableB. I am trying to execute two queries:
executeQuery(query1)
executeQuery(query2)
But I get the following error:
can not issue data manipulation statements with executeQuery().
What does this mean?
To manipulate data you actually need executeUpdate() rather than executeQuery().
Here's an extract from the executeUpdate() javadoc which is already an answer at its own:
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.
When executing DML statement , you should use executeUpdate/execute rather than executeQuery.
Here is a brief comparison :
If you're using spring boot, just add an #Modifying annotation.
#Modifying
#Query
(value = "UPDATE user SET middleName = 'Mudd' WHERE id = 1", nativeQuery = true)
void updateMiddleName();
For Delete query - Use #Modifying and #Transactional before the #Query like:-
#Repository
public interface CopyRepository extends JpaRepository<Copy, Integer> {
#Modifying
#Transactional
#Query(value = "DELETE FROM tbl_copy where trade_id = ?1 ; ", nativeQuery = true)
void deleteCopyByTradeId(Integer id);
}
It won't give the java.sql.SQLException: Can not issue data manipulation statements with executeQuery() error.
Edit:
Since this answer is getting many upvotes, I shall refer you to the documentation as well for more understanding.
#Transactional
By default, CRUD methods on repository instances are transactional. For read operations,
the transaction configuration readOnly flag is set to true.
All others are configured with a plain #Transactional so that default transaction
configuration applies.
#Modifying
Indicates a query method should be considered as modifying query as that changes the way
it needs to be executed. This annotation is only considered if used on query methods defined
through a Query annotation). It's not applied on custom implementation methods or queries
derived from the method name as they already have control over the underlying data access
APIs or specify if they are modifying by their name.
Queries that require a #Modifying annotation include INSERT, UPDATE, DELETE, and DDL
statements.
Use executeUpdate() to issue data manipulation statements. executeQuery() is only meant for SELECT queries (i.e. queries that return a result set).
#Modifying
#Transactional
#Query(value = "delete from cart_item where cart_cart_id=:cart", nativeQuery = true)
public void deleteByCart(#Param("cart") int cart);
Do not forget to add #Modifying and #Transnational before #query. it works for me.
To delete the record with some condition using native query with JPA the above mentioned annotations are important.
That's what executeUpdate is for.
Here's a very brief summary of the difference: http://www.coderanch.com/t/301594/JDBC/java/Difference-between-execute-executeQuery-executeUpdate
This code works for me: I set values whit an INSERT and get the LAST_INSERT_ID() of this value whit a SELECT; I use java NetBeans 8.1, MySql and java.JDBC.driver
try {
String Query = "INSERT INTO `stock`(`stock`, `min_stock`,
`id_stock`) VALUES ("
+ "\"" + p.get_Stock().getStock() + "\", "
+ "\"" + p.get_Stock().getStockMinimo() + "\","
+ "" + "null" + ")";
Statement st = miConexion.createStatement();
st.executeUpdate(Query);
java.sql.ResultSet rs;
rs = st.executeQuery("Select LAST_INSERT_ID() from stock limit 1");
rs.next(); //para posicionar el puntero en la primer fila
ultimo_id = rs.getInt("LAST_INSERT_ID()");
} catch (SqlException ex) { ex.printTrace;}
executeQuery() returns a ResultSet. I'm not as familiar with Java/MySQL, but to create indexes you probably want a executeUpdate().
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/java_swing_db", "root", "root");
Statement smt = conn.createStatement();
String sql = "SELECT * FROM `users` WHERE `email` = " + email + " AND `password` = " + password + " LIMIT 1;";
String registerSql = "INSERT INTO `users`(`email`, `password`, `name`) VALUES ('" + email + "','" + password + "','" + name + "')";
System.out.println("SQL: " + registerSql);
int result = smt.executeUpdate(registerSql);
System.out.println("Result: " + result);
if (result == 0) {
JOptionPane.showMessageDialog(this, "This is alredy exist");
} else {
JOptionPane.showMessageDialog(this, "Welcome, Your account is sucessfully created");
App.isLogin = true;
this.dispose();
new HomeFrame().show();
}
conn.close();
Besides executeUpdate() on the parentheses, you must also add a variable to use an SQL statement.
For example:
PreparedStatement pst = connection.prepareStatement(sql);
int numRowsChanged = pst.executeUpdate(sql);

Categories

Resources