JDBC: Generating the value of primary key for prepared statements [duplicate] - java

This question already has answers here:
Is there a way to retrieve the autoincrement ID from a prepared statement
(5 answers)
Illegal operation on empty result set [duplicate]
(2 answers)
Closed 7 years ago.
Suppose I want to add a new row to my table via JDBC. In my table, I have an auto incrementing primary key field (so I can update the table later), and another regular field.
userid BIGINT AUTO_INCREMENT PRIMARY KEY,
username TEXT,
Now, I am creating the new statement and executing it using prepared statements, like so:
//dummy execute to get the generated keys
stmt.execute("SELECT * FROM user;", Statement.RETURN_GENERATED_KEYS);
ResultSet rs = stmt.getGeneratedKeys();
int id=1;
//this is never executed, the resultset is always empty...
if(rs.next())
{
System.out.println("not empty");
id = rs.getInt(1);
}
System.out.println(id); //therefore, id is always 1
//prepare a statement to execute in SQL
stmt=con.prepareStatement("INSERT INTO user VALUES (?,?);", Statement.RETURN_GENERATED_KEYS);
//fill in the ?'s with their respective values
((PreparedStatement) stmt).setString(1, String.valueOf(id));
((PreparedStatement) stmt).setString(2, user);
//execute statement
((PreparedStatement) stmt).executeUpdate();
As you see, I want the value of the generated key so that I can use a prepared statement to update all the columns in the newly generated row (otherwise I get a No value specified for parameter 1 error).
But when I do the above code, I get an
Duplicate entry '1' for key 'PRIMARY'
This seems to me that the resultset is always empty. So I am not accessing the value correctly. Why is this so, and how can I fix this so that I can use my same structure of prepared statements to execute these queries?

You can call getGeneratedKeys only after you have executed you statement, not before. See https://docs.oracle.com/javase/8/docs/api/java/sql/Statement.html#getGeneratedKeys--
Simply preparing the statement does not generate the new key. Just drop the id column from your insert and insert only user.

1.Since your id is Auto Increment Column you should pass the value for that filed for first time (try to do it through MYSQL server directly.
2.Don't try to perform operations on empty result set.
3.In your case id always will be 1 since if statement doesn't execute.
Thank you.

Related

Use Value If Exists Else Use Default Value MySQL

Current Tools: Using Java to communicate with MySQL
I tried doing a search multiple times and ended up with this, but it didn't help me solve my problem. Google Search
I'm currently writing some query statements to try to save some information about my game objects to a database. I wanted to save the object's ID number if it wasn't 0, and to use the auto increment function otherwise if it was 0. For an example:
// (?,?) = (itemid, amount)
// itemid -> primary key and auto increment.
PreparedStatement ps = db.prepareStatement("INSERT INTO items (?,?)");
ps.setInt(1, item.id() == 0 ? >>>>DEFAULT<<<< : item.id());
ps.setInt(2, item.quantity());
The issue of course is that the way I'm doing isn't the correct way to tell MySQL to auto increment instead. Is there a way to do so? Also, the reason why I'm purposely inserting an ID in even though it's auto-increment is that I wrote a method previously that allowed me to save the original state of an item (thus preserving its stats). Upon loading this item, I want to be able to replace the current item and its stats with the newly loaded one.
Main Problem: Want to be able to insert a value if a condition is satisfied, otherwise use the auto-increment for primary key if possible. If there is something wrong with my approach, I'm open ears. Currently a beginner at databases!
EDIT:
As per MySQL suggestion, if you insert 0 into the id column, that column will automatically generate a sequence number.
Here: http://dev.mysql.com/doc/refman/5.7/en/example-auto-increment.html
Note that you should set the column (id) to AUTO-INCREMENT when the table is created. The auto increment will start at 1 so I you insert 0 the next max number will be inserted.
PreparedStatement ps = db.prepareStatement("INSERT INTO item(id, quantity) VALUES(?,?)");
ps.setInt(1, item.id());
ps.setInt(2, item.quantity());
Try it
PreparedStatement ps = db.prepareStatement("INSERT INTO items (?,?)");
ps.setInt(1, (item.id() == 0 ? 0 : item.id()));
ps.setInt(2, item.quantity());

If insert statement gives duplicate key exception(row id=1 found in table) how to update the statement in JDBC(Postgresql)

I have Stored bunch of insert statements in ArrayList.like below
List<String> script=new ArrayList<String>;
script.add("INSERT INTO PUBLIC.EMPLOYEE(ID, NAME) VALUES (1, 'Madhava'));
script.add(INSERT INTO PUBLIC.EMPLOYEE(ID, NAME) VALUES (2, 'Rao'));
script.add(INSERT INTO PUBLIC.ADDRESS(ID, CITY) VALUES(1, 'Bangalore'))
script.add(INSERT INTO PUBLIC.ADDRESS(ID, CITY) VALUES(2, 'Hyd'));
I created connection to the postgresql using jdbc i get executed statments using for loop like below
try{
Connection con=DBConnections.getPostgresConnection();
Statment statment=con.createStatment();
for(String query:script){
executeUpdate(query);
}
}catch(Exception e){
e.printStackTrace();
}
If i get duplication key exception(i.e.Already record exist in postgresDB).
org.postgresql.util.PSQLException: ERROR: duplicate key value
violates unique constraint "reports_uniqueness_index"
How to update the same statment(record) with update query into Postgres.
Is there any way to solve this ?
Is there any other better way to solve this?
Could you please explain...
Execute update sends a DML statement over to the database. Your database must already have a record which uses one of the primary keys either in the employees or address table.
You have to ensure you don't violate the primary key constraint. Violating the constraint is resulting in the exception.
Either change your query to an update statement, or delete the records which are causing conflict.
There is no way to get the key that caused the exception (though you can probably parse the error message, which is certainly not recommended).
Instead, you should try preventing this from ever happenning. There are at least 3 easy ways to accomplish this.
Make the database update the column
(in Postgresql you should use a serial type (which is basically an int data type)
CREATE TABLE employee
(
id serial NOT NULL,
--other columns here )
Your insert will now look like
script.add("INSERT INTO PUBLIC.EMPLOYEE(NAME) VALUES ('Madhava'));//no ID here
Create a sequence and have your JDBC code call the sequence' nexval method.
script.add("INSERT INTO PUBLIC.EMPLOYEE(ID, NAME) VALUES (YOUR_SEQ_NAME.NEXTVAL(), 'Madhava'));
Create a unique ID in Java (least recommended)
script.add("INSERT INTO PUBLIC.EMPLOYEE(ID, NAME) VALUES (UUID.random(), 'Madhava'));//or Math.random() etc

Get current sequence Id to store in other tables

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();

PreparedStatement for select count [duplicate]

This question already has answers here:
passing table and column name dynamically using bind variables
(2 answers)
Closed 8 years ago.
I have a program that will count the number of records from a variety of data sources. I have the database names and table names stored in array lists called database_names and table_names respectively. I am unable to get this to run:
for (int i = 0; i < table_names.size(); i++) {
String query = "select count(1) from ?.?";
PreparedStatement stmt = connection.prepareStatement(query);
stmt.setString(1, database_names.get(i));
stmt.setString(2, table_names.get(i));
ResultSet rs = stmt.executeQuery();
}
I get an ORA-00903: invalid table name error. I have set print statements to ensure that my database_names.get(i) and table_names.get(i) were printing out the right values. They were, and if I hardcode the database name and table name into my query string, the program is able to count the records.
How can I properly prepare my query statement so that it is of the form:
select count(1) from database_name.table_name
Oracle says: When you prepare a SQL statement or PL/SQL block that contains input data to be supplied at runtime, placeholders in the SQL statement or PL/SQL block mark where data must be supplied.
Schema and table name are not data, but data structures. During prepare phase Oracle parses statement, checks privileges. optimises plan. This is not possible without schema and tablename.
Oracle uses bind variables in execution phase, when your statement is prepared.
In your case you have to create new PreparedStatement for each table

How to get the serial id just after inserting a row? [duplicate]

This question already has answers here:
How to get a value from the last inserted row? [duplicate]
(14 answers)
Closed 9 years ago.
I have a table with row 'id' (a primary key) default set to serial in PostgreSQL. I insert into this row by calling
session.getCurrentSession().createSQLQuery("some insert query")
without adding any value into id as it is default set to serial.
How can I retrieve the `id' of just inserted row?
JDBC statements can return the generated keys. For instance, if the table has a single column id of type serial (probably PK) that is not mentioned in the insert SQL below, the generated value for this column can be obtained as:
PreparedStatement s = connection.createStatement
("INSERT INTO my_table (c,d) VALUES (1,2)",
Statement.RETURN_GENERATED_KEYS);
s.executeUpdate();
ResultSet keys = s.getGeneratedKeys();
int id = keys.getInt(1);
This is faster than sending the second query to obtain the sequence value or max column value later. Also depending on circumstances these two other solutions may not be not be thread safe.
Since it is serial you can use select max(id) from tableName
Using max(id) is a very bad idea. It will not give you the correct result
in case of multiple concurrent transactions. The only correct way is to use
curval() or the returning clause.
In posgresql: There is already a stackoverflow-question exists BTW.
`INSERT INTO tableName(id, name) VALUES(DEFAULT, 'bob') RETURNING id;`
(also)
Get a specific sequence:
SELECT currval('name_of_your_sequence');
Get the last value from the last sequence used:
SELECT lastval();
Manual: http://www.postgresql.org/docs/current/static/functions-sequence.html
For PHP-mysql users:
From php.net clickhere
<?php
$link = mysqli_connect('localhost', 'mysql_user', 'mysql_password');
if (!$link) {
die('Could not connect: ' . mysqli::$connect_error() );
}
mysqli::select_db('mydb');
mysqli::query("INSERT INTO mytable (product) values ('kossu')");
printf("Last inserted record has id %d\n", mysqli::$insert_id());
?>
But you need to connect for every query.
use SELECT CURRVAL(); . Typically used in conjunction with pg_get_serial_sequence
postgreSQL function for last inserted ID

Categories