This is my delete class that gets id as an input.
I succeeded to delete the row(for example row contained id '3' from my database) and now I want to update all the id-s.
for example: my rows were:
1 a5
2 f3
(3 t1 was deleted)
4 r2
so now the result should be updated:
1 a5
2 f3
3 r2
String delete = "DELETE from authors WHERE id = ?";
Class.forName("com.mysql.jdbc.Driver");
Connection con = DriverManager.getConnection(url, "root", "easttg");
PreparedStatement ps = con.prepareStatement(delete);
//updating the id
String sql = "Select id from authors";
PreparedStatement ps2 = con.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);
ps.setInt(1, id);
ps.executeUpdate();
con.close();
To update some row, you must use an update statement. Not a select statement:
update authors set id = ? where id = ?
That said: IDs are just technical identifiers for rows. They shouldn't be modified generally. And the reason why purely technical IDs are used is that they never need to be modified, which is a good thing because there might be dozens of other tables having foreign keys containing this same ID. The ID might also be part of some URL used to display the row in a web site, that many people could have bookmarked. The ID is... the identity of the row. You don't change an identity. If you do it, all kinds of problems occur, exactly as if you changed your own name.
Related
This question already has an answer here:
Why do I get java.sql.SQLException: ResultSet not open. Operation 'next' not permitted. java derby database?
(1 answer)
Closed 6 years ago.
In connection with another programming project, I am prototyping a JDBC project (with Netbeans, Java, and a Derby database). My program needs to iteratively update all the rows in a database table as follows:
There are three columns in the table: famousName, famousQuote, hashKey.
Originally, the famousQuote column contains a verbatim quote. I want to go down that column using a while loop, get the checksum of the ascii letters, bitwise "AND" with the hashKey value, and then replace the verbatim quote with an "encrypted" value.
As of right now, I try to extract the verbatim famousQuote using a ResultSet object, perform necessary encryption, and then an SQL statement that updates the value. All of this takes place in a while(rs.next()) loop as follows:
(pseudo-code): //all necessary database connections and variable declared here.
String sqlStatement = "Select * FROM mainTable ORDER BY famousName";
ResultSet rs = stmt.executeQuery(sqlStatement);
while(rs.next()){
tempString1 = rs.getString("famousQuote");
tempString2 = rs.getString("hashKey");
tempString3 = EncryptionAlgorithm.EncryptStatement(tempString1, tempString2);
sqlStatement = "UPDATE maintable SET famousQuote=tempString3 WHERE hashKey=tempString2";
(note, there is a bit of pseudo-code regarding the WHERE part,
but I'm sure it's immaterial to the error message I'm getting.)
stmt.executeUpdate(sqlStatement);
}
This seemed like a good idea until the program started throwing errors such as:
ResultSet not open. Operation 'next' not permitted. Verify that autoCommit is off
I later read in the documentation (concerning ResultSet):
A ResultSet object is automatically closed when the Statement object that generated it
is closed, re-executed, or used to retrieve the next result from a sequence of multiple results.
Lastly, I guess I could try moving the ResultSet rs declaration inside the while loop, so that it would instantiate a new ResultSet object, but I'm pretty sure this would lose my place in the database (re-updating the first row perpetually).
I'm now at a standstill on how to iterate my way down the table rows, executing my EncryptionAlgorithm on each quote, and then updating the column values in place.
I apologize in advance if my JDBC is a little rusty, but something like this might do the trick:
// 'conn' is your JDBC connection
Statement stmt = conn.createStatement();
PreparedStatement update = conn.prepareStatement(
"UPDATE maintable SET famousQuote=tempString3 WHERE hashKey=tempString2";
String sqlStatement = "Select * FROM mainTable ORDER BY famousName";
ResultSet rs = stmt.executeQuery(sqlStatement);
while(rs.next()){
tempString1 = rs.getString("famousQuote");
tempString2 = rs.getString("hashKey");
tempString3 = EncryptionAlgorithm.EncryptStatement(tempString1, tempString2);
update.setObject(1, tempString3);
update.setObject(2, tempString2);
update.executeUpdate(sqlStatement);
}
I have an insert clause and 2 columns which are named my_id and stream_id, I would like it so that each pair of (my_id,stream_id) is unique. For example my_id is a users personal unique id and it is always the same and stream_id correspond to different posts. For example if my_id is 4 and a stream_id is 8 then you can insert however since that is now in the database you can not do another insert on that same stream_id of 8. Here is my jdbc code
int stream_id= Integer.parseInt(requestData.get("stream_id"));
int my_id= Integer.parseInt(requestData.get("my_id"));
String insertTableSQL = "INSERT INTO reputation"
+ "(stream_id,my_id) VALUES"
+ "(?,?)";
dbConnection = DB.getConnection();
preparedStatement = dbConnection.prepareStatement(insertTableSQL, Statement.RETURN_GENERATED_KEYS);
preparedStatement.setInt(1, stream_id);
preparedStatement.setInt(2, my_id);
preparedStatement.executeUpdate();
Just to clarify I simply want to make sure that I have unique pairs in the database if I have a my_id of 5 and a stream_id of 9 then I should reject another pair of 5 and 9. The int variables already have those values I just do not know how to check if I have those pairs in the database; if I don't then continue with the insertion otherwise stop the inserts.
You should add a unique key in a database. If you want to handle at application site perhaps you could use Hibernate or JPA or JDO.
I want to be able to remove all data from 2 tables where the id of a user = the id given. I am using Java, Derby DB, Netbeans 7.3 Beta 2 and OS X Mountain Lion.
I have two tables (sorry about the huge image):
This is my statement so far:
String stmt2 = "DELETE FROM APP.PERSON JOIN APP.DATAVAULT WHERE PID = ?";
PreparedStatement ps2 = Main.getPreparedStatement(stmt2);
ps2 = conn.prepareStatement(stmt2);
ps2.setInt(1, user.getId());
ps2.executeUpdate();
System.out.println("Deleted");
I don't understand how I delete from APP.DATAVAULT as well as APP.PERSON. As you can see there is a foreign key within APP.DATAVAULT which is a users id.
I have tried many things such as:
String stmt2 = "DELETE FROM APP.PERSON, APP.DATAVAULT WHERE PID = ?";
and
String stmt2 = "DELETE FROM APP.PERSON AND APP.DATAVAULT WHERE PID = ?";
I understand that I must use the foreign key to delete from both, but I don't know how.
Unfortunately, per the docs, you cannot delete multiple tables with a single SQL query in Derby.
You can with some other RDBMS packages, such as MySQL... just not Derby.
The problem is following
By executing the below queries in SQL Plus, everything is working perfect:
column firstname new_value v_firstname
select firstname from tbcustomer where customer_id = 111
select '&v_firstname', wrk.* from tbwork where customer_id = 111
But when when i tried to execute these queries from Java program, i get java.sql.SQLException: ORA-00900: invalid SQL statement on the first SQL query
Connection connection = null;
Statement stat = null;
String query = "column due_date new_value v_due_date";
try {
// Load the JDBC driver
String driverName = "oracle.jdbc.driver.OracleDriver";
Class.forName(driverName);
connection = DriverManager.getConnection(url, username, password);
stat = connection.createStatement();
boolean res_num = stat.execute(query);
} catch (ClassNotFoundException e) {
// Could not find the database driver
} catch (SQLException e) {
e.printStackTrace();
}
Now the question is how to overcome this error and execute first query or do you have any other solution to define variable on the oracle session and use it in other SQL statements.
For instance third query is one of the many queries that i need to execute and all of them will have same first name field
column is a SQL*Plus command. It is not valid in SQL or PL/SQL so you cannot use it in a Java application.
Substitution variables like &v_firstname are also a SQL*Plus construct-- they are not valid in SQL or PL/SQL so you cannot use them in a Java application.
If your goal is to get the firstname from tbcustomer and all the columns from tbwork in a single query, you would need to join the two tables. Assuming that both tables have a customer_id column and that is how the two tables are supposed to be joined
SELECT cust.firstname,
work.*
FROM tbcustomer cust
JOIN tbwork work ON (cust.customer_id = work.customer_id)
WHERE cust.customer_id = 111
Assuming that you will be executing this query for multiple customer_id values, however, 111 should be a bind variable instead of a literal and your Java code should be using a PreparedStatement to prepare the SQL statement, then binding a value like 111 using the setInt method before executing the query.
If you want to break this into two database calls, you can simply do something like
PreparedStatement stmtGetFirstName = connection.prepareStatement("select firstname from tbcustomer where customer_id = ?");
stmtGetFirstName.setInt( 1, 111 );
ResultSet rsGetFirstName = stmtGetFirstName.executeQuery();
String firstName = rsGetFirstName.getString();
PreparedStatement stmtGetWork = connection.prepareStatement("select ?, work.* from tbwork where customer_id = ?");
stmtGetWork.setString( 1, firstName );
stmtGetWork.setInt( 2, 111 );
ResultSet rsGetWork = stmtGetWork.executeQuery();
If you can guarantee that all 600 million executions will occur in the same database session, you could use a database context. You would need to create the context and the package it uses in the database
SQL> create or replace context fname_ctx using scott.pkg_get_fname;
Context created.
SQL> ed
Wrote file afiedt.buf
1 create or replace package pkg_get_fname
2 is
3 procedure set_fname( p_customer_id in number );
4 function get_fname return varchar2;
5* end;
SQL> /
Package created.
SQL> create or replace package body pkg_get_fname
2 is
3 procedure set_fname( p_customer_id in number )
4 as
5 begin
-- Obviously, you'd get the data here from your table rather than hard-coding 'Bob'
6 dbms_session.set_context( 'fname_ctx', 'fname', 'Bob' );
7 end;
8
9 function get_fname
10 return varchar2
11 is
12 l_fname varchar2(100);
13 begin
14 l_fname := sys_context( 'fname_ctx', 'fname' );
15 return l_fname;
16 end;
17 end;
18 /
Package body created.
From Java, you could then call pkg_get_fname.set_fname(111) to set the context and use the function pkg_get_fname.get_fname in your query.
It seems odd, however, to be concerned about performance and to be planning to execute 600 million queries from Java against the database. That's going to involve a ton of round-trips over the network between the middle tier and the database server-- if you're really concerned about performance, you'd push that work to stored procedures in the database to eliminate the network round-trips. And the fact that you're executing them so many times makes me suspect that you're doing a lot of row-by-row processing rather than letting the database do set-based operations. That's also going to be a major source of poor performance. Plus, databases are born to join, so it's pretty unusual for a simple join like this to add appreciably to the cost of a query assuming that proper indexes are in place.
I'm trying to throw together a quick JDBC app using Postgres as the DB and am running into an interesting issue.
I currently have 2 tables, table1 and table2.
CREATE TABLE table1
(
a character varying NOT NULL,
b integer NOT NULL,
CONSTRAINT table1_pkey PRIMARY KEY (b)
)
CREATE TABLE table2
(
c character varying NOT NULL,
d integer,
CONSTRAINT table2_pkey PRIMARY KEY (c),
CONSTRAINT table2_d_fkey FOREIGN KEY (d),
REFERENCES table1(b) MATCH SIMPLE
ON UPDATE CSCADE ON DELETE CASCADE
)
As the backend of my program I'm SELECTing * and holding on to the ResultSet from my query. Each table has 1 row of simple values in it, doesn't seem to matter what they are.
My statement is created with the flags ResultSet.TYPE_SCROLL_INSENSITIVE and ResultSet.CONCUR_UPDATE. Although I have tried SCROLL_SENSITIVE as well.
If I try the following (assumgin ResultSet rs/rs2 are valid and point to table1/table2 respectively:
rs.first(); // move to the first row (only row)
rs.updateInt(2, 50); // update our primary key, which is also the cascading fk
// 50 could be any number
print(rs); // Will show the old value
rs.updateRow();
print(rs); // Will show the new value
rs2.refreshRow(); // make sure we get the latest data from table2
print(rs2); // will show the old data?
I was hoping to see the new values due to the cascade. If I quit and re-run the app, not changing any input, then it will print the correct table2 values. I'm guessing this is due to re-running the SELECT statement. If I look at the table by running psql or pgadmin3, the values seem like they're changing. So it seems like refreshRow() isn't bringing down the latest stuff. Would anyone have any idea why?
I'm using:
java 1.6_29
postgresql-9.1-901.jdbc4.jar
Any help would be appreciated.
I hope you got it sorted out since it's an old question but just for the record I post here a snippet that I tried and which is working for me:
Statement stmt = conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_UPDATABLE);
ResultSet rs = stmt.executeQuery("SELECT * FROM table1");
Statement stmt2 = conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_UPDATABLE);
ResultSet rs2 = stmt2.executeQuery("SELECT * FROM table2");
rs.first(); // move to the first row (only row)
rs.updateInt(2, 50); // update our primary key, which is also the
// cascading fk 50 could be any number
System.out.println(rs.getString(2)); // Prints the old value 12
rs.updateRow();
System.out.println(rs.getString(2)); // Prints the new value 50
rs2.first();
rs2.refreshRow(); // make sure we get the latest data from table2
System.out.println(rs2.getString(2)); // Prints the new value 50