JDBC insert statement error - sql

I cannot seem to figure out why it keep giving me this: executeQuery method can not be used for update. The way my code works is it takes in text from 5 jTextFields then converted to string double and int values. These values are sent to a method which will be pasted below. The problem is the sql statement is not working correctly at least I believe that is the problem. The columns are correct as well.
try{
String host = "jdbc:derby://localhost:1527/Comics";
String uName = "Brenton";
String uPass = "password";
Connection con = DriverManager.getConnection(host, uName, uPass);
Statement stat = con.createStatement();
String sql = "INSERT INTO LIBRARY(TITLE, ISSUE, PRICE, PUBLISHER, YEAR_ISSUED)" + "VALUES( '" + title + "', " + issue + ", " + price + ", '" + publisher + "', " + year + ")";
ResultSet rs = stat.executeQuery(sql);
}
catch(SQLException err){
System.out.println(err.getMessage());
}

Your immediate error (I think) is that your insert statement has no spaces between the end of the column names and the start of the VALUES keyword. But all this could be avoided if you used prepared statements:
String sql = "INSERT INTO LIBRARY(TITLE, ISSUE, PRICE, PUBLISHER, YEAR_ISSUED) VALUES(?, ?, ?, ?, ?)";
PreparedStatement ps = con.prepareStatement(sql);
ps.setString(1, title);
ps.setString(2, issue);
ps.setDouble(3, price);
ps.setString(4, publisher);
ps.setYear(5, year);
Note several obvious advantages here to this approach. First, you may write your insert query as a single string, with no concatenation. This helps avoid the mistake you made with whitespace. Second, statements do the work of escaping the string values (and any other value) properly.

What "executeQuery method can not be used for update" means is as follows:
Some SQL statements are used for queries. A SQL query is generally a SELECT statement, and it returns a set of rows from a database, which you process using a a JDBC ResultSet.
A SQL update is an INSERT, UPDATE, or DELETE statement, and it modifies rows in the database, but does not return any rows back to you (rather it returns the number of rows that you modified).
So, you can query, or you can update.
To query, you use executeQuery, and you get back a ResultSet.
To update, you use executeUpdate, and you get back a int.
For executeQuery, you pass a SELECT SQL statement.
For executeUpdate, you pass a INSERT, UPDATE, or DELETE SQL statement.
In your code, you are trying to perform a INSERT SQL statement, but you are calling executeQuery.

Related

When is ResultSet Needed

Which SQL statement needs a ResultSet to process return data? Update, Select, Insert, Delete? In JDBC
A ResultSet represents the database result set of a query. See https://docs.oracle.com/javase/8/docs/api/java/sql/ResultSet.html
Here is an example:
Statement statement = connection.createStatement();
String sql = "select * from users";
ResultSet result = statement.executeQuery(sql);
You can use the ResultSet to get the data from the table
while(result.next()) {
String name = result.getString("name");
System.out.println(name);
}
...or to update an entry
result.absolute(5); // moves the cursor to the fifth row of rs
result.updateString("name", "Cthullhu");
result.updateRow();
After use, you should close the ResultSet and the Statement
result.close();
statement.close();
You use a ResultSet after a select query using execute on the statement.
If you have update, insert or delete you can use executeUpdate on the statement
See this introduction from Oracle:
https://docs.oracle.com/javase/tutorial/jdbc/basics/processingsqlstatements.html#creating_statements

MyBatis Mapper with several SQLs in one method using DB2

I need to execute several SQL statements in one MyBatis Mapper method, because the SQLs are dependend on each other. With H2, this is no problem:
#Delete("DELETE FROM DETAIL_TABLE " +
" WHERE MASTER_ID IN " +
" (SELECT ID FROM MASTER WHERE BUSINESS_KEY = #{businessKey});" +
"DELETE FROM MASTER " +
" WHERE BUSINESS_KEY = #{businessKey}; ")
void delete(#Param("businessKey") Integer businessKey);
When switching to DB2 the statement does not work anymore, because the JDBC driver throws the following exception:
Caused by: com.ibm.db2.jcc.am.SqlSyntaxErrorException: DB2 SQL Error: SQLCODE=-104, SQLSTATE=42601, SQLERRMC=?;DELETE FROM MASTER WHERE;TAIL WHERE BUSINESS_KEY =;<space>, DRIVER=4.26.14
This is just an easy example to demonstrate the issue. I am aware that you can send a cascading delete statement in the shown situation.
I read a StackOverflow post, that multiple SQL statements in one call are not supported by some JDBC drivers and are not recommended, but sometimes you need to execute different SQLs in a certain order, so defining several MyBatis mapper methods does not solve the issue.
Does anybody has any idea how this can be achieved?
On the DB2 side, you can run a compound statement
"BEGIN ATOMIC" +
" DELETE FROM DETAIL_TABLE" +
" WHERE MASTER_ID IN" +
" (SELECT ID FROM MASTER WHERE BUSINESS_KEY = #{businessKey});" +
" DELETE FROM MASTER" +
" WHERE BUSINESS_KEY = #{businessKey};" +
"END"
or create and call a stored procedure

SQL syntax error in updating a database value

I'm update the money for one person only in a database. The money is saved as a currency and the email as a string. My SQL is throwing a syntax error
ADOQuery.sql.text:= ' UPDATE TblPlayerdetails SET Money = "' + Inttostr(NewAmount) + '" WHERE Email = "' + Playersemail + '"';
Newamount is an integer and email is a string.
I was hoping you would manage to work out what to do from the documentation I linked in comments, but on reflection I thought I had better provide a correct answer.
Set up the following code
procedure TForm1.Button1Click(Sender: TObject);
begin
AdoQuery2.SQL.Text := 'update moneytable set money = :money where id = :id';
AdoQuery2.Parameters.ParamByName('ID').Value := 1;
AdoQuery2.Parameters.ParamByName('Money').Value := 99;
AdoQuery2.ExecSQL;
end;
The line
AdoQuery2.SQL.Text := 'update moneytable set money = :money where id = :id';
sets up a parameterised UPDATE statement. The :id and :money are placeholders for parameter values which will be provided separately. The parameter names are ID and Money, though they could be given other names. Note that you could set up AdoQuery2's SQL.Text in the IDE at design time if you wanted to.
The next two lines
AdoQuery2.Parameters.ParamByName('ID').Value := 1;
AdoQuery2.Parameters.ParamByName('Money').Value := 99;
specify the values which the parameters are to be set to for when the UPDATE is actually executed. The ID value is the Row iD (aka primary key) of the row in the table which is to be updated. Before the UPDATE staement is actually executed, the AdoQuery parses the SQL and creates the parameters if they don't alteady exist (you can create them at design time in the IDE by editing the Parameters property of the AdoQuery.
Finally
AdoQuery2.ExecSQL;
is what actually executes the UPDATE statement. Note that you can repeat the steps of setting the parameter values and calling ExecSQL as many times as you want.
The main thing which was wrong with your UPDATE statement was that you were using double-quote (") marks, whereas when a SQL statement needs quote marks (and values of numeric columns do NOT) they should be single quotes('). A complication when constructing a SQL statement in Delphi code is that its syntax requires single quotes which are to be embedded in the SQL to be doubled up.
Note also that you should always used parameterised SQL for your SELECT, UPDATE, INSERT and DELETE statements as this helps protect your app against Sql injection. Making, say, an unparameterised statement accessible to the user can allow a malicious user to attempt to execute any SQL they wish.
In your question, you did not indicate what type of column is 'Money'. If it's varchar, char, then I understand why you might convert NewAmount to a string.
However, if the database expects numeric value (because the field is of type int, double, dec, or float), the syntax would be SET Money= '+ NewAmount +'.

select and delete record in transaction sql

I am using oracle as my database server. I have a simple sql table which stores codes for each member. I want to remove code from the table but also get the value of it.
SQL> describe member_code_store;
Name Null? Type
----------------------------------------- -------- ----------------------------
MEMBER NOT NULL NUMBER(38)
CODE NOT NULL VARCHAR2(30)
So I want to run below queries in a transaction
PreparedStatement pstmt = null;
ResultSet rs = null;
String query =
"SELECT code FROM member_code_store where coupon=? AND rownum=1";
Connection connection = DBConnection.getConnection();
pstmt = connection.prepareStatement(query);
pstmt.setString(1, String.valueOf(3));
rs = pstmt.executeQuery();
rs.next();
String code = rs.getString(1);
delete the code now
String query =
"delete from member_code_store where coupon =? AND code=?;";
Connection connection = DBConnection.getConnection();
pstmt = connection.prepareStatement(query);
pstmt.setString(1, String.valueOf(3));
pstmt.setString(2, code);
rs = pstmt.executeUpdate();
Problem with the above code is that multiple workers removing the codes will get the same code. How do I enclose the transaction so that I just lock the record instead of locking the whole table.
Or should I use procedures or packages which are more efficient?
Essentially you should use row lock. The example I show includes the nowait option, which wil return an error if you try to select the row that is lock and your code will have to handle that.
select code, rowid
from member_code_store
where coupon=? AND rownum=1
for update of code nowait
Save the rowid so that you have a variable to supply to the delete statement
delete from member_code_store
where rowid = :row_id

Multiple SQL Strings in one PreparedStatement

I've read on some other issues here, that it is not possible to use multiple different sql queries in one prepared statement.
String name = "XYZ";
int orderId = 10;
int imageId = 5;
String statement = "UPDATE T_order SET name = ? WHERE orderId = ?; UPDATE T_Order_Relations SET imageId = ? WHERE T_Order_Relations.orderId = ?";
PreparedStatement ps = connection.prepareStatement(statement)
ps.setString(1, name);
ps.setInt(2,orderId);
ps.setInt(3,imageId);
ps.setInt(4,orderId);
I had assumed, that this would lead to an exception from dbms or anything else, but actually i can execute this statement without any problems. Also the changes are done in db. So is it may be possible to use queries like this ?
Another question would be, are those both query executed like a single transaction (auto commit mode) ?
As DBMS im using PostgreSQL 9.3