I have looked at several link to retrieve the id with an insert using java, and I thought I would use the RETURNING clause.
my code:
Connection c = DriverManager.getConnection("jdbc:postgresql://localhost:5432/testdb?ssl=true&sslfactory=org.postgresql.ssl.NonValidatingFactory", "postgres","root");
String sql = "INSERT INTO main (nom_fichier, adate, mdate, cdate, size, chunknumber)"
+ " VALUES ('test',450,450,450,450,5)"
+ " Returning id"
+ ";";
Statement stmt = c.createStatement();
int rowNumber = stmt.executeUpdate(sql);
But I get this error:
Exception in thread "main" org.postgresql.util.PSQLException: a result was returned when none was expected.
at org.postgresql.jdbc2.AbstractJdbc2Statement.executeUpdate(AbstractJdbc2Statement.java:339)
at fr.infotel.postgre.TestPostgre.main(TestPostgre.java:25)
I also tried to use the Statement.RETURN_GENERATED_KEYS (withouth Returning clause) without success (I had nothing in the result set).
First Question: I would like to make the RETURNING statement work, as my request works in psql
Second Question: If the first is not possible, how can I have the same result
I am using postgres 9.3 with the postgres9.3.jdbc3 jar.
Thanks for your help.
Use ResultSet object instead of rowNumber
ResultSet resultSet = stmt.executeQuery(sql);
your query result now in resultSet variable.
Related
The query inside MySQL is working:
DELETE FROM f9.yoo
WHERE account_tags = '#8GGGJPUR9'
I can delete data inside MySQL, but the problem is whenever I try to remove the account_tags from my Java application, it throws an error:
java.sql.SQLSyntaxErrorException: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'DELETE FROM f9.yoo
WHERE account_tags = '#8GGGJPUR9'' at line 2
Here's my Java SQL query:
Statement statement = dbConnection.createStatement();
String sql = "SELECT * FROM "+databaseName+"."+tableName+";\n" +
"DELETE FROM "+databaseName+"."+tableName+"\n" +
"WHERE account_tags = '"+AccountTag+"';";
statement.executeQuery(sql);
The error isn't giving me much to work with, so I really have no idea what is wrong with the program.
Did you add the allowMultiQueries=true
If not then you can add that while you sending the connecting request to your database. So you need to append the allowMultiQueries=true in your to database URL.
Like this:
String dbUrl = "jdbc:mysql:///test?allowMultiQueries=true";
String sql = "DELETE FROM "+databaseName+"."+tableName+"\n" +
"WHERE account_tags = ?";
try (PreparedStatement statement = dbConnection.prepareStatement(sq)) {
statement.setString(1, AccountTag);
int updateCount = statement.executeUpdate();
System.out.printf("%s: %d records deleted.%n", tableName, updateCount);
}
The only thing used is the DELETE, for which one should use executeUpdate.
One definitely should use a PreparedStatement as many code checkers will give alarms otherwise. It escapes things like ', handles types of the arguments, and possible conversions, and especially is a security feature against SQL injection.
The System.out usage is bad style, better would be using a logger.
try-with-resources automatically closes the PreparedStatement even with a raised exception or break/return.
When doing both database operations, it seems better to use two (prepared) statements, as the first returns a ResultSet.
So:
String sql = SELECT * FROM "+databaseName+"."+tableName + "\n" +
"WHERE account_tags = ?";
try (PreparedStatement statement = dbConnection.prepareStatement(sq)) {
statement.setString(1, AccountTag);
try (ResultSet rs = statement.executeQuery()) {
...
}
}
Better to separate statements with an If condition :
String sql1="SELECT * FROM "+databaseName+"."+tableName;
String sql2="DELETE FROM "+databaseName+"."+tableName+" "+
"WHERE account_tags = '"+AccountTag+"';
statement.executeQuery(sql1);
statement.executeUpdate(sql2);
here my objective is to call a procedure over a database link in java. procedure takes one input and has got cursor as an output.
to check if my code is working properly, I created dummy procedure in my database and tried executing. it is working, able to get cursor and play with it.
however when i am calling some procedure over database link, getting error as
java.sql.SQLException: ORA-06550: line 1, column 7:
PLS-00201: identifier 'HR_CLICK_GET_EMP_DETAILS#IBSLUAT1.WORLD' must be declared
I had a call with developer who had created these procedure. according to him procedures exist at this end and access is already given to my user.
Now my questions and queries are
is there something different, i have to do while calling a procedure over database link(code is below)
what are the things i should be asking to sql developer. by the way database link is right.
String prc_name = "HR_CLICK_GET_CM_AND_ABOVE#IBSLUAT1.WORLD(?,?)";
String runSP = "{ call "+prc_name+" }";
String runSP1 = "{ call get_user_by_userId(?,?) }"; this one is working
try
{
Class.forName("oracle.jdbc.driver.OracleDriver");
Connection conn = DriverManager.getConnection(
"jdbc:oracle:thin:#xx.xx.xxx.xx:port:SERVICE", "username", "password"); // uat
CallableStatement cs = conn.prepareCall(runSP);
cs.setString(1, "705151");
cs.registerOutParameter(2, OracleTypes.CURSOR);
cs.execute();
// get refcursor and convert it to ResultSet
ResultSet resultSet = (ResultSet) cs.getObject(2);
ResultSetMetaData rsmd = resultSet.getMetaData();
int columnCount = rsmd.getColumnCount();
System.out.println("Total Columns in ResultSet : "+columnCount);
System.out.println("Now Analyzing column one by one:\n\n-----------------------------------------------");
for (int i = 1; i <= columnCount; i++ ) {
String name = rsmd.getColumnName(i);
System.out.println("Column No:"+i+">>>>>>>>"+name);
}
}
catch(SQLException s)
{
s.printStackTrace();
}
catch(ClassNotFoundException s)
{
s.printStackTrace();
}
thanks in advance
Ashish
Try to use the Oracle user's name who owns the procedure as a prefix:
username.HR_CLICK_GET_EMP_DETAILS#IBSLUAT1.WORLD
Answer is "synonym".
SQL Developer has created a synonym for HR_CLICK_GET_EMP_DETAILS as HR_CLICK_GET_EMP_DETAILS#IBSLUAT1.WORLD
that is what he informed me, I could not quite wrap my head around that but able to hit the procedure.
but now , able to get get the metadata of a result set but unable to traverse rows.
I'm getting an error:
java.sql.SQLException: ORA-24338: statement handle not executed
at oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:112)
at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:331)
at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:288)
at oracle.jdbc.driver.T4C8Oall.receive(T4C8Oall.java:743)
at oracle.jdbc.driver.T4CStatement.doOall8(T4CStatement.java:207)
at oracle.jdbc.driver.T4CStatement.fetch(T4CStatement.java:1018)
at oracle.jdbc.driver.OracleResultSetImpl.close_or_fetch_from_next(OracleResultSetImpl.java:291)
at oracle.jdbc.driver.OracleResultSetImpl.next(OracleResultSetImpl.java:213)
at ashishtest.StoredProcedureCursor.main(StoredProcedureCursor.java:80)
I guess, new forum is required for this error.
also I am not marking this as solved as not sure how solution works.
This question already has an answer here:
ResultSet is not for INSERT query? Error message: Type mismatch: cannot convert from int to String
(1 answer)
Closed 5 years ago.
I am getting a error on the resultset rs part where netbeans shows the error as
incompatible types:int cannot be converted to resultset
Class.forName("java.sql.Driver");
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/mysql?useSSL=false", "root", "abc");
Statement stmt = conn.createStatement();
String query = "SELECT * FROM patient WHERE Mobile_No='" + mobno + "';"; /*Get the value from the database*/
ResultSet rs = stmt.executeUpdate(query);/*Part where the error is appearing*/
while (rs.next()) {
String Name = rs.getString("Name");
String Age = rs.getString("Age");
String Mobile = rs.getString("Mobile_No");
String gender = rs.getString("Gender");
String symptoms = rs.getString("Symptoms");
model.addRow(new Object[]{Name, Age, Mobile, gender, symptoms});
}
rs.close();
stmt.close();
conn.close();
Use stmt.executeQuery(String sql), it returns ResultSet.
If you want a ResultSet returned you should use executeQuery, not executeUpdate.
The stmt.executeUpdate(query); doesn't fit for an SELECT query.
You need to replace it by stmt.executeQuery(query);
Well the method executeUpdate returns a int not a results set, seen in the documentation here: https://docs.oracle.com/javase/7/docs/api/java/sql/Statement.html#executeUpdate(java.lang.String)
the integer being return being either (1) the row count for SQL Data Manipulation Language (DML) statements or (2) 0 for SQL statements that return nothing
the method you are actually want to use is executeQuery and the documentation for that can be found at:
https://docs.oracle.com/javase/7/docs/api/java/sql/Statement.html#executeQuery(java.lang.String)
According the Javadoc (https://docs.oracle.com/javase/9/docs/api/java/sql/Statement.html#executeUpdate-java.lang.String-), stmt.executeUpdate(query); returns an int and not a ResultSet object.
From the Javadoc :
Returns:
either (1) the row count for SQL Data Manipulation Language (DML) statements or (2) 0 for SQL statements that return nothing
I think you must use stmt.executeQuery(query); instead, which return the ResultSet you expect. You're doing a SELECT and not an INSERT, UPDATE, or DELETE operation.
I believe people have already answered your question, which is statement.executeUpdate(query) returns the number of how many rows has been affected by executing the query, and you should use statement.executeQuery(query) instead ..
But this part String query = "SELECT * FROM patient WHERE Mobile_No = '" + mobno + "';" is very bad approach, it will leave the door opened for SQL injection, you should use PreparedStatement instead of Statement
I have the following prepared statement for sql in Java :
com.mysql.jdbc.JDBC4PreparedStatement#6e56103e:
INSERT INTO `game` (Id , GameStart ,Name, Lenght, MapVersion, Mode)VALUES(2502591,'2000-03-02 02:02:02','5x5 aptb wdw','00:55:48','DotA v6.75b.w3x','aptb ')ON DUPLICATE KEY UPDATE `Id`=VALUES(Id),`GameStart` = VALUES(GameStart),`Name`=VALUES(Name),`Lenght`=VALUES(Lenght),`MapVersion`=VALUES(MapVersion),`Mode`=VALUES(Mode).
When I execute it in Eclipse I get the following error:
com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '?,?,?,?,?,?)ON DUPLICATE KEY UPDATE `Id`=VALUES(Id),`GameStart` = VALUES(GameSta' at line 1.
But at the same time when I execute the same query in SQLyog I don't get an error. Rows are updated. What can be a problem? Thanks in advance
Code:
Class.forName("com.mysql.jdbc.Driver");
Connection con = DriverManager.getConnection("jdbc:mysql://localhost:3306/dota","root","root");
PreparedStatement updateGame = null;
String updatingGame = "INSERT INTO `game` (Id , GameStart ,Name, Lenght, MapVersion, Mode)" +
"VALUES(?,?,?,?,?,?)" +
"ON DUPLICATE KEY UPDATE " +
"`Id`=VALUES(Id),"+
"`GameStart` = VALUES(GameStart)," +
"`Name`=VALUES(Name)," +
"`Lenght`=VALUES(Lenght)," +
"`MapVersion`=VALUES(MapVersion)," +
"`Mode`=VALUES(Mode)";
con.setAutoCommit(false);
updateGame=con.prepareStatement(updatingGame);
updateGame.setInt(1, game.Id);
Timestamp timestamp = new Timestamp(100,2,2,2,2,2,2);
updateGame.setTimestamp(2,timestamp);
updateGame.setString(3, game.GameName);
updateGame.setTime(4, (Time) game.Time);
updateGame.setString(5, game.MapVersion);
updateGame.setString(6, game.Mode);
updateGame.executeUpdate(updatingGame);
And on:
updateGame.executeUpdate(updatingGame);
I get an error
Firstly if you are using a preparedStatement you have to do it this way
String query="Insert into tablename (col1, col2) values(?,?)";
PreparedStatement stmnt = //get the statement
stmnt.setString(1, "col1val");
stmnt.setString(2, "col2val");
You are inserting a duplicate value on the primary key.
Follow the #chaitanya10 suggestion, use PreparedStatement
How is your knowledge about Object Orientation? As I can see you aren't using correctly encapsulation.
Found my mistake. I should use only executeUpdate() instead of executeUpdate(updatingGame) ;, because if I use it with parameter, I will overwrite values whiten by
updateGame.setInt(1, game.Id);
Timestamp timestamp = new Timestamp(100,2,2,2,2,2,2);
updateGame.setTimestamp(2,timestamp);
updateGame.setString(3, game.GameName);
updateGame.setTime(4, (Time) game.Time);
updateGame.setString(5, game.MapVersion);
updateGame.setString(6, game.Mode);
This question already has answers here:
How to get the insert ID in JDBC?
(14 answers)
Closed 7 years ago.
Is there some way to get a value from the last inserted row?
I am inserting a row where the PK will automatically increase, and I would like to get this PK. Only the PK is guaranteed to be unique in the table.
I am using Java with a JDBC and PostgreSQL.
With PostgreSQL you can do it via the RETURNING keyword:
PostgresSQL - RETURNING
INSERT INTO mytable( field_1, field_2,... )
VALUES ( value_1, value_2 ) RETURNING anyfield
It will return the value of "anyfield". "anyfield" may be a sequence or not.
To use it with JDBC, do:
ResultSet rs = statement.executeQuery("INSERT ... RETURNING ID");
rs.next();
rs.getInt(1);
See the API docs for java.sql.Statement.
Basically, when you call executeUpdate() or executeQuery(), use the Statement.RETURN_GENERATED_KEYS constant. You can then call getGeneratedKeys to get the auto-generated keys of all rows created by that execution. (Assuming your JDBC driver provides it.)
It goes something along the lines of this:
Statement stmt = conn.createStatement();
stmt.execute(sql, Statement.RETURN_GENERATED_KEYS);
ResultSet keyset = stmt.getGeneratedKeys();
If you're using JDBC 3.0, then you can get the value of the PK as soon as you inserted it.
Here's an article that talks about how : https://www.ibm.com/developerworks/java/library/j-jdbcnew/
Statement stmt = conn.createStatement();
// Obtain the generated key that results from the query.
stmt.executeUpdate("INSERT INTO authors " +
"(first_name, last_name) " +
"VALUES ('George', 'Orwell')",
Statement.RETURN_GENERATED_KEYS);
ResultSet rs = stmt.getGeneratedKeys();
if ( rs.next() ) {
// Retrieve the auto generated key(s).
int key = rs.getInt(1);
}
Since PostgreSQL JDBC driver version 8.4-701 the PreparedStatement#getGeneratedKeys() is finally fully functional. We use it here almost one year in production to our full satisfaction.
In "plain JDBC" the PreparedStatement needs to be created as follows to make it to return the keys:
statement = connection.prepareStatement(SQL, Statement.RETURN_GENERATED_KEYS);
You can download the current JDBC driver version here (which is at the moment still 8.4-701).
The sequences in postgresql are transaction safe. So you can use the
currval(sequence)
Quote:
currval
Return the value most recently obtained by nextval for this sequence
in the current session. (An error is
reported if nextval has never been
called for this sequence in this
session.) Notice that because this is
returning a session-local value, it
gives a predictable answer even if
other sessions are executing nextval
meanwhile.
Here is how I solved it, based on the answers here:
Connection conn = ConnectToDB(); //ConnectToDB establishes a connection to the database.
String sql = "INSERT INTO \"TableName\"" +
"(\"Column1\", \"Column2\",\"Column3\",\"Column4\")" +
"VALUES ('value1',value2, 'value3', 'value4') RETURNING
\"TableName\".\"TableId\"";
PreparedStatement prpState = conn.prepareStatement(sql);
ResultSet rs = prpState.executeQuery();
if(rs.next()){
System.out.println(rs.getInt(1));
}
If you are using Statement, go for the following
//MY_NUMBER is the column name in the database
String generatedColumns[] = {"MY_NUMBER"};
Statement stmt = conn.createStatement();
//String sql holds the insert query
stmt.executeUpdate(sql, generatedColumns);
ResultSet rs = stmt.getGeneratedKeys();
// The generated id
if(rs.next())
long key = rs.getLong(1);
If you are using PreparedStatement, go for the following
String generatedColumns[] = {"MY_NUMBER"};
PreparedStatement pstmt = conn.prepareStatement(sql,generatedColumns);
pstmt.setString(1, "qwerty");
pstmt.execute();
ResultSet rs = pstmt.getGeneratedKeys();
if(rs.next())
long key = rs.getLong(1);
Use sequences in postgres for id columns:
INSERT mytable(myid) VALUES (nextval('MySequence'));
SELECT currval('MySequence');
currval will return the current value of the sequence in the same session.
(In MS SQL, you would use ##identity or SCOPE_IDENTITY())
PreparedStatement stmt = getConnection(PROJECTDB + 2)
.prepareStatement("INSERT INTO fonts (font_size) VALUES(?) RETURNING fonts.*");
stmt.setString(1, "986");
ResultSet res = stmt.executeQuery();
while (res.next()) {
System.out.println("Generated key: " + res.getLong(1));
System.out.println("Generated key: " + res.getInt(2));
System.out.println("Generated key: " + res.getInt(3));
}
stmt.close();
Don't use SELECT currval('MySequence') - the value gets incremented on inserts that fail.
For MyBatis 3.0.4 with Annotations and Postgresql driver 9.0-801.jdbc4 you define an interface method in your Mapper like
public interface ObjectiveMapper {
#Select("insert into objectives" +
" (code,title,description) values" +
" (#{code}, #{title}, #{description}) returning id")
int insert(Objective anObjective);
Note that #Select is used instead of #Insert.
for example:
Connection conn = null;
PreparedStatement sth = null;
ResultSet rs =null;
try {
conn = delegate.getConnection();
sth = conn.prepareStatement(INSERT_SQL);
sth.setString(1, pais.getNombre());
sth.executeUpdate();
rs=sth.getGeneratedKeys();
if(rs.next()){
Integer id = (Integer) rs.getInt(1);
pais.setId(id);
}
}
with ,Statement.RETURN_GENERATED_KEYS);" no found.
Use that simple code:
// Do your insert code
myDataBase.execSQL("INSERT INTO TABLE_NAME (FIELD_NAME1,FIELD_NAME2,...)VALUES (VALUE1,VALUE2,...)");
// Use the sqlite function "last_insert_rowid"
Cursor last_id_inserted = yourBD.rawQuery("SELECT last_insert_rowid()", null);
// Retrieve data from cursor.
last_id_inserted.moveToFirst(); // Don't forget that!
ultimo_id = last_id_inserted.getLong(0); // For Java, the result is returned on Long type (64)
If you are in a transaction you can use SELECT lastval() after an insert to get the last generated id.