SELECT then UPDATE all rows from RESULTSET - java

I am wanting to update all the rows in the RESULTSET from the SELECT in one single UPDATE query.
Here is what I have come up with so far:
SELECT id_queue, status FROM table WHERE status IN (0,2) ORDER BY status, id_queue ASC FOR UPDATE;
UPDATE table SET status = 97 WHERE id_queue= " + id_combined + ";
So, I guess I need to take all the id_queue ids, put them together like 1,2,3,4,5,6,7,8 into id_combined.
Any idea the best way to do this in JAVA?
NOTE: I am not just trying to update all with status 0 & 2 to 97, I want to use the select resultset somewhere else.

Not sure what SQL dialect you are using, but this is worth a try:
update table set status = 97 where ID_queue in
(SELECT id_queue FROM table WHERE status IN (0,2))

Use a StringBuilder to collect the id numbers returned in the ResultSet, and then use this to build an update query.
First, execute the query and collect the ID's.
StringBuilder ids = new StringBuilder();
Statement statement = this.conn.createStatement();
statement.executeQuery("SELECT id_queue, status FROM table WHERE status IN (0,2) ORDER BY status, id_queue ASC;");
ResultSet rs = statement.getResultSet();
while (rs.next()) {
if (ids.length() > 0)
ids.append(',');
ids.append(rs.getInt("id_queue"));
}
// use the resultset for whatever else you want
rs.close();
Then, perform the update.
if (ids.length() > 0) {
statement = this.conn.createStatement();
statement.executeUpdate("UPDATE table SET status = 97 WHERE id_queue In ("+ids.toString()+");");
}

One approach to do this is a nested query. That is, you can put a SELECT inside your UPDATE sort of like this:
UPDATE table SET status = 97 WHERE id_queue IN (SELECT id_queue
FROM table
WHERE status IN(0,2))
Google for sql 'nested query' or 'subquery' for more info.

My thought would be something along the lines for (not working code)
List<Integer> ids = new ArrayList<Integer>();
for(Row row : ResultSet.rows()) {
ids.add(row.get("id_queue");
}
String sql = "UPDATE table SET status = 97 WHERE id_queue IN (" +
StringUtils.join(ids, ",") +
")";
Using the StringUtils class from Apache.
Obviously, since you said you don't want to convert ALL items in the ResultSet to status 97:
You can't just have an SQL query that does the SELECT/SET at the same time (unless you can formulate in SQL what the additional criteria are), and
You'll need up modify the for loop to select out only the rows you actually want to modify
For completeness sake, the following would do the update (if you wanted to modify all rows) with pure SQL
UPDATE table SET status = 97
WHERE status IN (0,2)

to avoid the error you need to give the SELECT statment an alias:
try this:
UPDATE table SET status = 97 WHERE id_queue IN (SELECT * FROM (SELECT id_queue
FROM table
WHERE status IN(0,2)) MyResult)
MyResult is an alias to the select query

Related

update statement with dynamically changing rows using prepared statement

I am planning to execute an update statement using a prepared statement that makes use of a dynamically changing number of columns. for eg: in the first update statement I update only name and age of a table. in the second instance, I update age, city, state, country..etc. in the next instance, I update 150 columns like this.
can someone provide me what is the perfect approach for this in java?
following is the example
If the user provides input for name and age then I update
UPDATE table1 set name = <> ,age = <>;
If the user provides input for city name state country and pin then the update statement should be like this-
UPDATE table1 set name = <>, city = <>,state= <>,country=<>, pin = <>;
Build your sql query like this
update demotable set col1 = case when #col1 is null then col1 else #col1 end
OR
Here #col is passed as value from front end.
from which you may create dynamic sql
declare #col1 nvarchar(max) /// from front you can pass your column value with its column name like: col1 = 'col1'
declare #Query = 'update demotable set = ' + #col1 /// it create query as update demotable set col1 = 'col1'
PREPARE stmt1 FROM #Query ;
EXECUTE stmt1
DEALLOCATE PREPARE stmt1;
I am new to MYSQL but this logic will surely work.
You can write one statement like this:
UPDATE table1
SET name = COALESCE(?, name),
age = COALESCE(?, age),
city = COALESCE(?, city),
. . .
Notes:
This assumes that the values are not being set to NULL.
The ? is a placeholder for a parameter. Don't munge query strings with user input.
Presumably you want a WHERE clause to limit what rows get updated.

How can a jdbcTemplate execute an update statement and return variable

I am newbie to work on spring, and now I got a query but not sure how to use jdbcTemplate to work on it, the query is as follow:
UPDATE table set Seq = #seq := Seq + 1 WHERE id= ?; SELECT #seq as total;
I try to use jdbcTemplate.executeQuery but it will shows up error:
Can not issue data manipulation statements with executeQuery().
I try to use jdbcTemplate.executeUpdate, but seems it only return affected row
Is there anyone know how I can achieve this query and return the updated value?
You should be able to execute the UPDATE statement first using update and then execute the SELECT statement using queryForObject. The variable is persisted across the session bound to the same connection.
jdbcTemplate.update("UPDATE table set Seq = #seq := Seq + 1 WHERE id= ?", yourId);
int total = jdbcTemplate.queryForObject("SELECT #seq as total", Integer.class);

select JDBC query not retrieving records in order

I am trying to fetch records from oracle db. I have a select query which has an order by clause implemented. Now when I fire the query on the toad i get the results in correct order. i.e the order of the records at 10:00 AM is like
Record 1, Record 2,Record 3 and at 10:05 its Record 1, Record 2, Record 3. This is what i need.
Now when iam fetching it through java code, JDBC . I try to iterate the resultset, but here at 10:05 am I am getting the order like Record 2, Record 1, Record 3. Due to this when i am adding the records to the arraylist the order is not mantained.
I dont want to sort the records of arraylist after adding.
Can someone please let me know why using jdbc the records are not fetched in the order we can see using toad ?
Sample code
try{
List<TestObjVO> testResults = new ArrayList<TestObjVO>();
double statusValue = 0;
//Connection code
pstmt = conn.prepareStatement(QUERY);
ResultSet rs = pstmt.executeQuery();
while (rs.next()) {
testObj = new TestObjVO();
String date = rs.getString(1);
String status = rs.getString(2);
String svc_nm= rs.getString(3);
if("SUCCESS".equalsIgnoreCase(status)){
statusValue = 1;
}else if("ERROR".equalsIgnoreCase(status)){
statusValue = -1;
}
testObj.setTime(date);
testObj.setStatus(statusValue);
testObj.setSvc_nm(svc_nm);
testResults.add(testObj);
}
SELECT query
SELECT to_char(PROBING_DATE,'DD-MM-YYYY HH24:MI:SS') AS PROBING_DATE, STATUS, SERVICE_NAME FROM TABLE_NAME WHERE PROBING_DATE >= (sysdate-30/1440) ORDER BY PROBING_DATE,SERVICE_NAME
Table
create table TABLE_NAME(
probing_date TIMESTAMP(6) not null,
status VARCHAR2(8) not null,
service_name VARCHAR2(128) not null
)
Change your select to something like this:
SELECT to_char(PROBING_DATE,'DD-MM-YYYY HH24:MI:SS') AS PROBING_DATE_STR,
PROBING_DATE,
STATUS,
SERVICE_NAME
FROM TABLE_NAME
WHERE PROBING_DATE >= (sysdate-30/1440)
ORDER BY PROBING_DATE,SERVICE_NAME;
Note there's an extra field returned and is the raw TIMESTAMP field.

Mysql JDBC - not entering ResultSet + incorrect no. of rows

I came across a problem with going through a ResultSet I'm generating from my MySQL db. My query should return at most one row per table (I'm looping through several tables searching by employee number). I've entered data in some of the tables; but my test o/p says that the resultset contains 0 rows and doesn't go through the ResultSet at all. The o/p line it's supposed to print never appears. It was in a while loop before I realised that it'd be returning at most one row, at which point I just swapped the while(rs.next()) for an if(rs.first()). Still no luck. Any suggestions?
My code looks like this:
try
{
rsTablesList = stmt.executeQuery("show tables;");
while(rsTablesList.next())
{
String tableName = rsTablesList.getString(1);
//checking if that table is a non-event table; loop is skipped in such a case
if(tableName.equalsIgnoreCase("emp"))
{
System.out.println("NOT IN EMP");
continue;
}
System.out.println("i'm in " + tableName); //tells us which table we're in
int checkEmpno = Integer.parseInt(empNoLbl.getText()); //search key
Statement s = con.createStatement();
query = "select 'eventname','lastrenewaldate', 'expdate' from " + tableName + " where 'empno'=" + checkEmpno + ";"; // eventname,
System.out.println("query is \n\t" + query + "");
rsEventDetails = s.executeQuery(query) ;
System.out.println("query executed\n");
//next two lines for the number of rows
rsEventDetails.last();
System.out.println("no. of rows is " + rsEventDetails.getRow()+ "\n\n");
if(rsEventDetails.first())
{
System.out.println("inside the if");
// i will add the row now
System.out.println("i will add the row now");
// cdTableModel.addRow(new Object[] {evtname,lastRenewalDate,expiryDate});
}
}
}
My output looks like this:
I'm in crm
query is
select 'eventname','lastrenewaldate', 'expdate' from crm where 'empno'=17;
query executed
no. of rows is 0
I'm in dgr
query is
select 'eventname','lastrenewaldate', 'expdate' from dgr where 'empno'=17;
query executed
no. of rows is 0
NOT IN EMP
I'm in eng_prof
query is
select 'eventname','lastrenewaldate', 'expdate' from eng_prof where 'empno'=17;
query executed
no. of rows is 0
I'm in frtol
query is
select 'eventname','lastrenewaldate', 'expdate' from frtol where 'empno'=17;
query executed
no. of rows is 0
(and so on, upto 17 tables.)
The '17' in the query is the empno that I've pulled from the user.
The thing is that I've already entered data in the first two tables, crm and dgr. The same query in the command line interface works; this morning, I tried the program out and it returned data for the one table that had data in it (crm). The next time onwards, nothing.
Context: I'm working on a school project to create some software for my dad's office, it'll help them organise the training etc schedules for the employees. (a little like Google Calendar I guess.) I'm using Netbeans and Mysql on Linux Mint. There are about 17 tables in the database. The user selects an employee name and the program searches for all entries in the database that correspond to an 'event' (my generic name for a test/training/other required event) and puts them into a JTable.
The single quotes around the column names and table name in the creation of the query seem to have caused the problem. On changing them to backticks, retrieval works fine and the data comes in as expected.
Thank you, #juergend (especially for the nice explanation) and #nailgun!

Invalid operation for read only resultset: updateString

Following is my code(Re-constructed) which select & update STATUS field depending upon the conditions. (Using Servlets, Oracle as Backend and JDBC driver)
ResultSet rs=null;
String query = "select A.NAME, A.ADDRESS, A.STATUS, B.CLASS from TABLE_ONE A, TABLE_TWO B where A.STATUS='N'";
pstmt = con.prepareStatement(query,ResultSet.TYPE_SCROLL_INSENSITIVE,ResultSet.CONCUR_UPDATABLE);
rs = pstmt.executeQuery();
while(rs.next())
{
String name = rs.getString("NAME");
String address = rs.getString("ADDRESS");
String class = rs.getString("CLASS");
String msg = //Other statements to check what status to be set
if(msg.equals("OK"))
rs.updateString("STATUS", "S");
else
rs.updateString("STATUS", "E");
rs.updateRow();
}
I am getting the error while updating:
java.sql.SQLException: Invalid operation for read only resultset: updateString
Any suggestions will be appreciated.
Update 1:
The same code was working when select statement was selecting data from single table, so is there any issue when selecting data from two tables in single query?
[Note: As #javaBeginner has mentioned in comments it will work only for one table.]
The following limitations are placed on queries for enhanced result sets. Failure to follow these guidelines will result in the JDBC driver choosing an alternative result set type or concurrency type.
To produce an updatable result set (from specification):
A query can select from only a single table and cannot contain any join operations.
In addition, for inserts to be feasible, the query must select all non-nullable columns and all columns that do not have a default value.
* A query cannot use "SELECT * ". (But see the workaround below.)
* A query must select table columns only. It cannot select derived columns or aggregates such as the SUM or MAX of a set of columns.
To produce a scroll-sensitive result set:
A query cannot use "SELECT * ". (But see the workaround below.)
A query can select from only a single table.
Try This :
Statement stmt = conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,ResultSet.CONCUR_UPDATABLE);
//Execute a query
String sql = "select A.NAME, A.ADDRESS, A.STATUS, B.CLASS from TABLE_ONE A, TABLE_TWO B where A.STATUS='N'";
ResultSet rs = stmt.executeQuery(sql);
//Extract data from result set
rs.beforeFirst();
while(rs.next())
{
String name = rs.getString("NAME");
String address = rs.getString("ADDRESS");
String class = rs.getString("CLASS");
String msg = //Other statements to check what status to be set
if(msg.equals("OK"))
rs.updateString("STATUS", "S");
else
rs.updateString("STATUS", "E");
rs.updateRow();
}
Just changed Prepared statement to create statement
SELECT * makes the resultSet readonly. SELECT COLUMN_NAME makes it updatable.
So instead of SELECT * FROM TABLE use SELECT COLUMN1, COLUMN2, ... FROM TABLE.

Categories

Resources