Get current sequence Id to store in other tables - java

We have multiple tables and all are related with first table's primary key (example: id). Id is configured as a sequence and while inserting data into to first table we are using sequence.nextval in the insert query.
Now while inserting data to other tables, how to get current sequence value or current Id.
We have tried below options:
sequence.currval, directly in the insert statement
2.select sequence.currval from dual
Above two options throwing error while using getJdbcTemplate().update().
Could anyone please suggest how to get current sequence value to pass to other tables after inserting data into first table??

If you want to insert the same id (which comes from a sequence) to different tables, simple get it form the first insert and use it in the other inserts.
PrepearedStatement stmt1 = conn.prepareStatement("INSERT INTO TABLE1 (id) VALUES(yoursequence.nextval)", Statemet.RETURN_GENERATED_KEYS);
stmt1.executeUpdate();
ResultSet rs = stmt1.getGeneratedKeys();
rs.next();
long id = rs.getLong(1);
PrepearedStatement stmt2 = conn.prepareStatement("INSERT INTO TABLE2 (id) VALUES(?)");
stmt2.setLong(1,id);
stmt2.executeUpdate();

Related

What is the return type for a field for a query in Postgres with 0 rows?

I have a table accounts in Postgres which had id and name as fields. id is the primary key.
I want to fetch the last primary key inserted into the table using this query :-
select id from accounts order by id desc limit 1 ;
Using a preparedStatement I run this query and get the value for my next primary key by incrementing it by 1.
String query="SELECT "+columnName+" FROM "+TableName+" ORDER BY "+columnName+" DESC limit 1";
PreparedStatement stmt=conn.prepareStatement(query);
ResultSet rs= stmt.executeQuery();
int counter= rs.getInt(1);
My question is if there are 0 rows, what will be the counter value?
If the value is null which i don't think can be stored in int, how do I assign it a starting primary int key value say 10 ?
You shouldn't be doing that, so here's what I believe is the best answer.
Instead, define your id as auto-incrementing which postgres manages:
create table account (
id serial not null primary key,
...
)
Then execute an insert:
insert into account (col1, col2, ...) values (..., ...) -- omit id
And the new account will get the next number, which you can get from the result returned from the insert, or in postgres you can use a regular query to get it
insert into account (col1, col2, ...) values (..., ...) -- omit id
returning id
Note the change in name from accounts to account - naming tables are a singular noun is best practice and makes sense: accounts.surname is nonsense, but account.surname is how we speak and think.

How to delete multiple rows from multiple tables using Where clause?

Using an Oracle DB, I need to select all the IDs from a table where a condition exists, then delete the rows from multiple tables where that ID exists. The pseudocode would be something like:
SELECT ID FROM TABLE1 WHERE AGE > ?
DELETE FROM TABLE1 WHERE ID = <all IDs received from SELECT>
DELETE FROM TABLE2 WHERE ID = <all IDs received from SELECT>
DELETE FROM TABLE3 WHERE ID = <all IDs received from SELECT>
What is the best and most efficient way to do this?
I was thinking something like the following, but wanted to know if there was a better way.
PreparedStatement selectStmt = conn.prepareStatment("SELECT ID FROM TABLE1 WHERE AGE > ?");
selectStmt.setInt(1, age);
ResultSet rs = selectStmt.executeQuery():
PreparedStatement delStmt1 = conn.prepareStatment("DELETE FROM TABLE1 WHERE ID = ?");
PreparedStatement delStmt2 = conn.prepareStatment("DELETE FROM TABLE2 WHERE ID = ?");
PreparedStatement delStmt3 = conn.prepareStatment("DELETE FROM TABLE3 WHERE ID = ?");
while(rs.next())
{
String id = rs.getString("ID");
delStmt1.setString(1, id);
delStmt1.addBatch();
delStmt2.setString(1, id);
delStmt2.addBatch();
delStmt3.setString(1, id);
delStmt3.addBatch();
}
delStmt1.executeBatch();
delStmt2.executeBatch();
delStmt3.executeBatch();
Is there a better/more efficient way?
You could do it with one DELETE statement if two of your 3 tables (for example "table2" and "table3") are child tables of the parent table (for example "table1") that have a "ON DELETE CASCADE" option.
This means that the two child tables have a column (example column "id" of "table2" and "table3") that has a foreign key constraint with "ON DELETE CASCADE" option that references the primary key column of the parent table (example column "id" of "table1"). This way only deleting from the parent table would automatically delete associated rows in the child tables.
Check out this in more detail : http://www.techonthenet.com/oracle/foreign_keys/foreign_delete.php
If you delete only few records of a large tables ensure that an index on the
column ID is defined.
To delete the records from the table TABLE2 and 3 the best strategy is to use the CASCADE DELETE as proposed by
#ivanzg - if this is not possible, see below.
To delete from TABLE1 a far superior option that a batch delete on a row basis, use signle delete using the age based predicate:
PreparedStatement stmt = con.prepareStatement("DELETE FROM TABLE1 WHERE age > ?")
stmt.setInt(1,60)
Integer rowCount = stmt.executeUpdate()
If you can't cascade delete, use for the table2 and 3 the same concept as above but with the following statment:
DELETE FROM TABLE2/*or 3*/ WHERE ID in (SELECT ID FROM TABLE1 WHERE age > ?)
General best practice - minimum logic in client, whole logic in the database server. The database should be able to do reasonable execution plan
- see the index note above.
DELETE statement operates a table per statement. However the main implementations support triggers or other mechanisms that perform subordinate modifications. For example Oracle's CREATE TRIGGER.
However developers might end up figuring out what is the database doing behind their backs. (When/Why to use Cascading in SQL Server?)
Alternatively, if you need to use an intermediate result in your delete statements. You might use a temporal table in your batch (as proposed here).
As a side note, I see not transaction control (setAutoCommit(false) ... commit() in your example code. I guess that might be for the sake of simplicity.
Also you are executing 3 different delete batches (one for each table) instead of one. That might negate the benefit of using PreparedStatement.

Delete row from table

I want to delete the current row displayed in jframe from the table contact
I wrote the code
try
{
conn = java.sql.DriverManager.getConnection(connectionURL, "usrnme", "pswd");
Statement stmt = conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,ResultSet.CONCUR_UPDATABLE);//also tried with ResultSet.TYPE_SCROLL_SENSITIVE
rs.deleteRow();
rs.next();//it may or may not include in code
}
catch(Exception e){System.out.println( "JDBC error: " + e );}
sql query
String sql="SELECT * FROM contact order by first_name, last_name";
rs=stmnt.executeQuery(sql);
but it throws an exception while running
JDBC error: java.sql.SQLException: 'deleteRow' not allowed because the ResultSet is not an updatable ResultSet.
Help me!
I suggest to do it totally in SQL, where you need to additionally select the (internal) rowid of every row
SELECT c.*, c.rowid FROM contact c ORDER BY first_name, last_name
and afterward delete a row by it row id
DELETE FROM contact c WHERE c.rowid = (?)
this works for Oracle, but every Databasetype does use internal rowid's. For MYSQl you get the rowid by using #rowid as far as I remember
Instead of ResultSet.TYPE_SCROLL_INSENSITIVE, try ResultSet.TYPE_SCROLL_SENSITIVE. That might do the trick. If that doesn't work, try an SQL DELETE statement (w3schools.com) instead to delete the row.
Edit: Now that I reread your code: you need to move to the next row before you call deleteRow. Opening a statement sets the cursor before the first row. If your call to next returns true, your cursor points to the first row. Only if the cursor points to a valid row can you delete the row. HTH.
To make use of updatable ResultSet , your table must contain primary key column. It is the link between data present in ResultSet and DB. Since I infer from your comments your table does not contain primary key, you can delete row using sql query.
String sql = "DELETE FROM contact WHERE first_name='test'";
stmt.executeUpdate(sql);

Insert only if row doesn't exist

I am using PreparedStatement to prepare sql queries. I want to insert a row in table if and only if it doesn't exist.
I tried this -
INSERT INTO users (userId) VALUES (?) ON DUPLICATE KEY UPDATE userId = ?
But this will unnecessarily update the userId.
How can i insert the userId here ?
INSERT INTO users
(userId)
SELECT ?
WHERE NOT EXISTS
(
SELECT *
FROM users
where userId = ?
)
You may use
INSERT IGNORE INTO users (userId) VALUES (?)
But you should understand why do you want ignore errors.
on duplicate key does not work correctly when the table is an innodb. It creates exactly the problem you are describing. If you need the functionality of an innodb, then should you first check the existence of the row, otherwise can you convert the table to a myisam table.
edit: if you need to check the existence of the row before the decision to insert or update, then would I advice you to use a stored procedure.
DELIMITER //
CREATE PROCEDURE adjustusers(IN pId int)
BEGIN
DECLARE userid int;
select count(id) into userid from users where id = pId;
if userid = 1 then
update users set id = pId where id = pId;
else
insert into users(id) values(pId);
end if;
END //
DELIMITER ;
A stored procedure is precompiled, just as a prepared statement. Hence no SQL injection problems and some more functionality and only one call to the database.

Retrieving data from a relational database

I have set up 2 two tables - table userid and table data in phpmyadmin. The userid table consists of a single column - id and the table data consists of the following columns- id|name|price. I have added an index in the column id of table userid to point to id of the table data. Now i have a user who makes certain selections inside an android application. I want to insert this data into the table data. I know i have to use jdbc and know how to enter data for table without any index. But i am confused as to how to go about doing it in the case of related tables. The userid is obtained from this link http://android-developers.blogspot.in/2011/03/identifying-app-installations.html. Would someone please tell me how to enter the data using java. (The confusion is how to enter the userid and the corresponding data ).
As long as you're aware of the user id when you're inserting a new record into the data table that's all you need. Basically you'll have:
Statement stmt = conn.createStatement();
stmt.executeUpdate( "INSERT INTO data (id, name, price) VALUES ('id from userid table', 'a name', 'a price')");
Obviously the params aren't escaped properly (they really should be) and there's no testing for errors, but that would get you started.
Then to, for example, select all the data related to a given userid, you would do something like:
Statement stmt = conn.createStatement();
stmt.executeQuery( "SELECT * FROM userid LEFT JOIN data WHERE userid.id = data.id" );

Categories