Multiple SQL Strings in one PreparedStatement - sql

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

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

JDBC insert statement error

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.

Where Clause is not working in Update but working in Select in Oracle DB

I am trying to execute the below update query
update custom_field cfe set cfe.field_value =:valueId where cp_entity_id = :cId
0 rows updated.
This is not updating any row but same where clause is working fine with select query and returns 1 row
select * from custom_field where cp_entity_id = :cId
Also, if i hardcode the value of cId parameter then update works fine but I am executing it from java program so it's not possible for me to hardcode the value
Also cp_entity_id column is a foreign key.
Try this, I faced similar issue.
Use this
select primary_key from custom_field where cp_entity_id = :cId query to find out primary key and Then use that primary key in your where clause of update query.
One of the ways to set parameter is explained here.
PreparedStatement ps = conn.prepareStatement(
"UPDATE Messages SET description = ?, author = ? WHERE id = ? AND seq_num = ?");
// set the preparedstatement parameters
ps.setString(1,description);
ps.setString(2,author);
ps.setInt(3,id);
ps.setInt(4,seqNum);
// call executeUpdate to execute our sql update statement
ps.executeUpdate();
ps.close();

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

parameterizing all JOIN data in a large UPDATE operation

I have an app that makes a bunch of updates to objects hydrated with data from an SQL Server table and then writes the updates objects' data back to the DB in one query. I'm trying to convert this into a parameterized query so that I don't have to do manual escaping, conversions, etc.
Here's the most straightforward example query:
UPDATE TestTable
SET [Status] = DataToUpdate.[Status], City = DataToUpdate.City
FROM TestTable
JOIN
(
VALUES --this is the data to parameterize
(1, 0, 'A City'),
(2, 0, 'Another City')
) AS DataToUpdate(Id, [Status], City)
ON DataToUpdate.Id = TestTable.Id
I've also played around with using OPENXML to do this, but I'm still forced to write a bunch of escaping code when adding the values to the query. Any ideas on how to make this more elegant? I am open to ADO.NET/T-SQL solutions or platform-agnostic solutions.
One thought I had (but I don't really like how dynamic this is) is to dynamically create parameters and then add them to an ADO.NET SqlConnection, e.g.
for(int i = 0; i < data.Length; i++)
{
string paramPrefix = string.Format("#Item{0}", i);
valuesString.AppendFormat("{0}({1}Status)", Environment.NewLine, paramPrefix);
var statusParam = new SqlParameter(
string.Format("{0}Status", paramPrefix),
System.Data.SqlDbType.Int)
{ Value = data[i].Status };
command.Parameters.Add(statusParam);
}
I'm not exactly sure how you store your application data (and I don't have enough rep points to post comments) so I will ASSUME that the records are held in an object CityAndStatus which is comprised of int Id, string Status, string City held in a List<CityAndStatus> called data. That way you can deal with each record one at a time. I made Status a string so you can convert it to an int in your application.
With those assumptions:
I would create a stored procedure https://msdn.microsoft.com/en-us/library/ms345415.aspx in SQL Server that updates your table one record at at time.
CREATE PROCEDURE updateCityData (
#Id INT
,#Status INT
,#City VARCHAR(50)
)
AS
BEGIN TRAN
UPDATE TestTable
SET [Status] = #Status
,City = #City
WHERE Id = #Id
COMMIT
RETURN
GO
Then I would call the stored procedure https://support.microsoft.com/en-us/kb/310070 from your ADO.NET application inside a foreach loop that goes through each record that you need to update.
SqlConnection cn = new SqlConnection(connectionString);
cn.Open();
foreach (CityAndStatus item in data)
{
SqlCommand cmd = new SqlCommand("updateCityData",cn);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("#Id", item.Id);
cmd.Parameters.AddWithValue("#Status", Convert.ToInt32(item.Status));
cmd.Parameters.AddWithValue("#City", item.User);
cmd.ExecuteNonQuery();
cmd.Dispose();
}
cn.Close();
After that you should be good. The one thing left that might stand in your way is SQL Server makes web application users grant permission to execute stored procedures. So in SQL Server you may have to do something like this to allow your application to fire the stored proc.
GRANT EXECUTE
ON updateCityData
TO whateverRoleYouHaveGivenPermissionToExecuteStoredProcedures
Good Luck