So i have this query using DATEDIFF function on MS SQL Server?
SELECT DATEDIFF(DAY,(select StartDate from CarOrder where OrderID= 59),(select EndDate from CarOrder where OrderID= 59))
This work fine and the result is 10 but i dont know how to get the return value and use it in this function for java
public int getDateDiff(int OrderID){
Connection conn = DBConnection.getConnection();
int datediff;
String getdiffSQL = "SELECT DATEDIFF(DAY,(select StartDate from CarOrder where OrderID = ? ) ,(select EndDate from CarOrder where OrderID= ?) )";
try {
PreparedStatement pstm = conn.prepareStatement(getdiffSQL);
pstm.setInt(1, OrderID);
pstm.setInt(2, OrderID);
int nRows = pstm.executeUpdate();
return nRows;
} catch (SQLException ex) {
System.out.println("Error: " + ex.getMessage());
} finally {
DBConnection.closeConnection(conn);
}
}
i want it to return the date diff number so that it is a variable i can use in java, how can i do this ?
Thank You.
Use ResultSet
You need to capture the ResultSet, and access the rows of that ResultSet (in this case a single row). If you are executing a query, call executeQuery on your PreparedStatement, thereby producing a ResultSet.
Use the modern try-with-resources syntax to automatically close your database resources. You can drop the finally clauses; no need to call closeXXX on your database resources as that chore is handled for you.
I have not tried executing the following code example, but I hope it is close to what you need. I am using the alternate SELECT line suggested in comment by Martin Smith; I’ve not put thought into that as it is not the core of your Question.
String sql = "SELECT DATEDIFF( DAY , StartDate , EndDate ) FROM CarOrder WHERE OrderID = ? ;" ;
Integer diff = null ;
try (
Connection conn = myDataSource.getConnection() ;
PreparedStatement pstmt = conn.prepareStatement ( sql ) ;
) {
pstmt.setInt( 1 , orderId ) ;
try (
ResultSet rs = pstmt.executeQuery( sql ) ;
) {
while ( rs.next ( ) ) {
diff = rs.getInt( 1 ) ; // Auto-boxing `int` to `Integer`.
}
}
}
} catch ( SQLException e ) {
e.printStackTrace ( ); // Handle error condition however you see fit.
}
if( null == diff ) {
System.out.println( "mission failed." ) ;
} else {
System.out.println( "mission succeeded. Diff is: " + diff ) ;
}
For real work, I would also test to make sure I had only one row returned (make sure that while loop runs exactly once rather than zero or more than once).
If this is not clear to you about the various database resources (DataSource, Connection, PreparedStatement, ResultSet), you should put down the IDE and do some more study of the Oracle Tutorial on JDBC matters, and do some searching/studying of Stack Overflow on the topic.
Store the result of the query in the ResultSet object, and then pick the value of the appropriate column by using of {YOUR_RESULT_SET}.getYourDataType(columnNumber).
Related
i'm trying to check if a data is already present in my database and comparing it with user input from my java application.
But when i use equals method, i have always a false return... And i would like a "true" return.
I don't understand why it doesn't match...
Here is my code :
public boolean getTicketWithRegVehicleNumber(String vehicleRegNumber) {
Connection con = null;
boolean valueReturn = false;
try {
con = dataBaseConfig.getConnection();
PreparedStatement ps = con.prepareStatement(DBConstants.GET_VEHICLE_REG_NUMBER);
ps.setString(1, vehicleRegNumber);
ResultSet rs = ps.executeQuery();
//TODO trouver comment tester l'egalité entre la db et la saisie user
String sqlRequestResult = DBConstants.GET_VEHICLE_REG_NUMBER;
if (sqlRequestResult.equals(vehicleRegNumber)){
valueReturn = true;
}
dataBaseConfig.closeResultSet(rs);
dataBaseConfig.closePreparedStatement(ps);
} catch (Exception ex) {
logger.error("Error fetching next available slot", ex);
} finally {
dataBaseConfig.closeConnection(con);
}
return valueReturn;
}
here is my SQL request :
public static final String GET_VEHICLE_REG_NUMBER = "select t.VEHICLE_REG_NUMBER from ticket t where t.VEHICLE_REG_NUMBER = ? ";
To sum up, i have a boolean variable : returnValue, and i want that when i use equals method on my SQL selected data (a VARCHAR type that i put in a String variable) and user's input which is a String , my boolean return true.
Thanks for helping :-)
See correct Answer by Dravidian. Your code neglected to access the ResultSet you named rs. So you never retrieved any data from the database.
Here is a complete example app using the H2 Database Engine.
We hardcode the query result presented in the result set as a single row with a single column of text type with a value of Crêpe. Notice how we access the ResultSet using a loop, accessing the retrieved value with a call to getString. Then we compare strings using String#equals.
Also, notice how this example code uses try-with-resources syntax to automatically close resources such as our Connection, Statement, and ResultSet objects. Make a habit of using try-with-resources syntax to simplify your JDBC code (and similarly file i/o code, etc.).
import org.h2.jdbcx.JdbcDataSource;
import java.sql.*;
import java.time.*;
import java.util.*;
public class App5
{
public static void main ( String[] args )
{
App5 app = new App5();
app.doIt();
}
private void doIt ( )
{
JdbcDataSource dataSource = Objects.requireNonNull( new JdbcDataSource() ); // Implementation of `DataSource` bundled with H2.
dataSource.setURL( "jdbc:h2:mem:text_match;DB_CLOSE_DELAY=-1" ); // Set `DB_CLOSE_DELAY` to `-1` to keep in-memory database in existence after connection closes.
dataSource.setUser( "scott" );
dataSource.setPassword( "tiger" );
try (
Connection conn = dataSource.getConnection() ;
)
{
String sql = "SELECT 'Crêpe' ;";
try (
Statement stmt = conn.createStatement() ;
ResultSet rs = stmt.executeQuery( sql ) ;
)
{
while ( rs.next() )
{
//Retrieve by column number.
String result = rs.getString( 1 );
//Display values
System.out.println( "result: " + result );
System.out.println( "result equals crepe: " + result.equals( "crepe" ) ); // False. Missing the circumflex.
System.out.println( "result equals crêpe: " + result.equals( "crêpe" ) ); // False. Lowercase `c` does not match `C`.
System.out.println( "result equals Crêpe: " + result.equals( "Crêpe" ) ); // True.
}
}
}
catch ( SQLException e )
{
e.printStackTrace();
}
}
}
When run.
result: Crêpe
result equals crepe: false
result equals crêpe: false
result equals Crêpe: true
You're comparing your plain sql query string (DBConstants.GET_VEHICLE_REG_NUMBER) to the vehicleRegNumber parameter and no wonder they don't match.
What you need to compare is the result from your ps.executeQuery(); which is assigned to ResultSet rs.
Read the ResultSet javadoc to understand how you can extract data from it - https://docs.oracle.com/javase/8/docs/api/java/sql/ResultSet.html.
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 3 years ago.
Improve this question
I have tried to add stmt.executeUpdate(); to insert to the database, but it still not working!! After processing, no error is shown but no data is insert into the database.
try {
// do insert
String preparedSQL = "insert into abc (NUM, ID) VALUES (?,?)";
for(int i = 1; i < r.length; i++)
{
stmt = conn.prepareStatement(preparedSQL);
// SQL parameters
setString(stmt, i++, Num);
setString(stmt, i++, r[i]);
stmt.executeQuery();
}
stmt.executeUpdate();
stmt.close();
} catch (SQLException e) {
PrintWriter out = new PrintWriter(new OutputStreamWriter(res
.getOutputStream(), "Big5"), true);
res.setContentType("text/html; charset=utf-8");
res.setHeader("cache-control", "no-cache");
res.setHeader("Pragma", "no-cache");
res.setIntHeader("expiry", -1000);
out.println("..<!--" + RSCommonUtil.HTMLEncode(e.toString()) + "para in title not valid" +
RSCommonUtil.HTMLEncode(pDate.toString())
+ " " + RSCommonUtil.HTMLEncode(startPubDateAndEndPubDate[0].toString()) + " "
+ RSCommonUtil.HTMLEncode(startPubDateAndEndPubDate[1].toString()) + "-->");
debug.p("insert error" + e);
failed = true;
} finally {
try {
// finalize DB
if (stmt != null) {
stmt.close();
stmt = null;
}
} catch (SQLException sqle) {
}
}
executeUpdate is for create, drop, insert, update, delete etc., (i.e., updating your table), executeQuery is for select. It returns an instance of ResultSet.
See here for simple explanation: https://www.javatpoint.com/PreparedStatement-interface
Also, your setString has an incorrect number of parameters and it should be called as a method of the statement object, and the parameterIndex (first parameter of the setString method) should just be i, as you will otherwise increment three times for each iteration. I also changed the loop to start at 0, don't know why you would start at 1 as a normal array should start at 0.
So your main block would be something like this:
...
// do insert
String preparedSQL = "insert into abc (NUM, ID) VALUES (?,?)";
PreparedStatement stmt = conn.prepareStatement(preparedSQL);
for(int i = 0; i < r.length; i++)
{
// SQL parameters
stmt.setString(i, Num);
stmt.setString(i, r[i]);
stmt.executeUpdate();
}
stmt.close();
...
Inside the try block, try rewriting the code as follows:
String preparedSQL = "insert into abc (NUM, ID) VALUES (?,?)";
for(int i = 1; i < r.length; i++)
{
stmt = conn.prepareStatement(preparedSQL);
// SQL parameters
stmt.setString(1, Num);
stmt.setString(2, r[i]);
stmt.executeUpdate();
stmt.close();
}
The setString method takes only two parameters.
public void setString(int paramIndex, String value)
Here 'paramIndex' refers to the index of the parameter in your prepared statement and 'value' refers to which value you want to insert at that index.
The executeQuery() method of prepared statement interface is used for SELECT queries. But in your case, since the statement is an INSERT query, you will have to use executeUpdate() method. This method is used for CREATE, DROP, UPDATE, INSERT, etc. statements.
Refer this for more information regarding prepared statements and sample code.
The other Answers by yalda and by Nitish are both correct, with good advice. Ditto for some comments on the Question. I can add one more thought, plus a full working example app that writes and reads rows using the H2 Database Engine.
Try-With-Resources
Use the try-with-resources syntax to shorten your code, and guarantee your resources get closed appropriately.
Example app
package work.basil.example;
import org.h2.jdbcx.JdbcDataSource;
import java.sql.*;
import java.time.OffsetDateTime;
import java.time.ZoneOffset;
import java.util.UUID;
public class H2DateTimeExample
{
public static void main ( String[] args )
{
H2DateTimeExample app = new H2DateTimeExample ();
app.demo ();
}
private void demo ( )
{
JdbcDataSource dataSource = new JdbcDataSource ();
dataSource.setURL ( "jdbc:h2:mem:offsetdatetime_example_db;DB_CLOSE_DELAY=-1" ); // Set `DB_CLOSE_DELAY` to `-1` to keep in-memory database in existence after connection closes.
dataSource.setUser ( "scott" );
dataSource.setPassword ( "tiger" );
// Create table.
String sql = "CREATE TABLE person_ ( \n" +
" pkey_ UUID NOT NULL DEFAULT RANDOM_UUID() PRIMARY KEY , \n" +
" name_ VARCHAR NOT NULL , \n" +
"first_contacted_ TIMESTAMP WITH TIME ZONE NOT NULL " +
") ;";
// System.out.println ( sql );
try (
Connection conn = dataSource.getConnection () ;
Statement stmt = conn.createStatement () ;
)
{
stmt.execute ( sql );
} catch ( SQLException e )
{
e.printStackTrace ();
}
// Insert row.
sql = "INSERT INTO person_ ( name_ , first_contacted_ ) \n";
sql += "VALUES ( ? , ? ) \n";
sql += ";";
try (
Connection conn = dataSource.getConnection () ;
PreparedStatement pstmt = conn.prepareStatement ( sql , Statement.RETURN_GENERATED_KEYS ) ;
)
{
OffsetDateTime odt = OffsetDateTime.now ( ZoneOffset.UTC );
pstmt.setString ( 1 , "Jesse Johnson" );
pstmt.setObject ( 2 , odt );
pstmt.executeUpdate ();
ResultSet rs = pstmt.getGeneratedKeys ();
// System.out.println( "INFO - Reporting generated keys." );
// while ( rs.next() ) {
// UUID uuid = rs.getObject( 1 , UUID.class );
// System.out.println( "generated keys: " + uuid );
// }
} catch ( SQLException e )
{
e.printStackTrace ();
}
// Query table.
sql = "TABLE person_ ;";
try (
Connection conn = dataSource.getConnection () ;
PreparedStatement pstmt = conn.prepareStatement ( sql ) ;
)
{
try ( ResultSet rs = pstmt.executeQuery () ; )
{
while ( rs.next () )
{
UUID pkey = rs.getObject ( "pkey_" , UUID.class );
String name = rs.getString ( "name_" );
OffsetDateTime firstContacted = rs.getObject ( "first_contacted_" , OffsetDateTime.class );
System.out.println ( "pkey: " + pkey + " | name: " + name + " | firstContacted: " + firstContacted );
}
}
} catch ( SQLException e )
{
e.printStackTrace ();
}
System.out.println ( "Done." );
}
}
pkey: 0819123b-5c7f-4859-bd1b-f9dac82b855f | name: Jesse Johnson | firstContacted: 2019-08-03T18:16:30.367840Z
Done.
I have a local SQL-Server running MariaDB and need to query Data from a database using Java and JDBC. I can connect to the Database and also write data, but a simple SELECT does not work.
I already tried to use different versions of the mysql-java-connector and checked that the SQL-Server is up to date.
Connecting to Database:
//Check wether connection already exists
if(connection != null && !connection.isClosed()){
return;
}
//Create new connection
connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/statdb", "root", "");
System.out.println("Connected to Database");
//Update guilds from Database
updateGuildsInDatabase();
The method called at the end looks like this:
private void updateGuildsInDatabase() throws SQLException {
//Check for not existing connection
if(connection == null || connection.isClosed()){
init();
return;
}
ArrayList<String> localInDb = new ArrayList<>();
Statement qGStmt = connection.createStatement();
//Execute Query
ResultSet guilds = qGStmt.executeQuery("SELECT * FROM guilds;");
guilds.first();
//Adding results to List
while(guilds.next()){
localInDb.add(guilds.getString("guild_uid").toLowerCase());
}
System.out.println("Queried: " + localInDb.size());
this.guildsInDb = localInDb;
}
The table "guilds" in the database "statdb" has two columns named "guild_uid" (primary key, varchar) and "display_name" (varchar). I've added one entry with the values "guild_1" and "Test Guild".
As I have one entry in the table 'guilds' I would expect the console to look like this:
Connected to Database
Queried: 1
But the actual output looks like this:
Connected to Database
Queried: 0
The ResultSet#first() method itself moves the cursor to the first row of the result set. The ResultSet#next() method then moves the cursor forward by one, and reads whatever record is there, if a record is there.
Therefore, using your pattern will always result in skipping the first record from the result set. If the result set happens to have only a single record, then the record count will appear to be zero.
You should probably remove the call to ResultSet#first(). Use this instead:
ResultSet guilds = qGStmt.executeQuery("SELECT * FROM guilds;");
while(guilds.next()) {
localInDb.add(guilds.getString("guild_uid").toLowerCase());
}
System.out.println("Queried: " + localInDb.size());
this.guildsInDb = localInDb;
The reason why calling ResultSet#next() on a fresh result set logically works, is that by default a JDBC result set actually does not start pointing to the first record. Rather, we typically advance it to the first record with the very first call to ResultSet#next().
I don't think you need guilds.first(). Try removing it.
According to the ResultSet JavaDoc:
A ResultSet cursor is initially positioned before the first row; the first call to the method next makes the first row the current row; the second call makes the second row the current row, and so on.
I believe what is happening here is, guilds.first() set the cursor from before first row to first row. And guilds.next() in the while loop move the cursor to further one step ahead. Therefore, you are missing the first row.
The other two Answers are correct, you are skipping the first row when retrieving from the result set. No need for your line guilds.first(); as they explained, the result set automatically points at first row by default.
Example code, retrieving from ResultSet
Here is a complete example using the H2 Database Engine. This shows creating a new database (in-memory, not persisted to disk), adding a table, populating that table with a few rows, and then retrieving all those rows through a ResultSet.
The key line is while ( rs.next() ) {.
package work.basil.example;
import java.sql.*;
import java.util.*;
import org.h2.jdbcx.JdbcDataSource;
import javax.sql.DataSource;
public class GuildDemo {
public static void main ( String[] args ) {
GuildDemo app = new GuildDemo();
app.doIt();
}
private void doIt ( ) {
DataSource dataSource = null;
final String catalogName = "guild_demo_";
final String tableName = "guild_";
// Verify JDBC driver.
try {
Class.forName( "org.h2.Driver" );
JdbcDataSource ds = new JdbcDataSource(); // The `javax.sql.DataSource` interface implemented by `org.h2.jdbcx.JdbcDataSource`.
ds.setURL( "jdbc:h2:mem:" + catalogName + ";DB_CLOSE_DELAY=-1" ); // Set delay to -1 to keep in-memory database even after last connection closed.
ds.setUser( "scott" );
ds.setPassword( "tiger" );
ds.setDescription( "Dummy database for demo showing how to retrieve rows from a ResultSet." );
dataSource = ds; // Generalize from the concrete class to the interface.
} catch ( ClassNotFoundException e ) {
e.printStackTrace();
return;
}
// Connect, and create database.
try (
Connection conn = dataSource.getConnection() ;
) {
String sql = null;
// Create table.
try ( Statement stmt = conn.createStatement() ; ) {
sql = "CREATE TABLE " + "guild_" + " ( \n" +
" pkey_ UUID DEFAULT random_uuid() PRIMARY KEY , \n" +
" name_ VARCHAR NOT NULL \n" +
") ; \n";
System.out.println( "TRACE - SQL:\n" + sql );
stmt.execute( sql );
}
// Add rows.
sql = "INSERT INTO guild_ ( name_ ) \n" +
"VALUES ( ? ) " +
"; ";
List < String > names = List.of( "Alpha" , "Beta" , "Gamma" , "Delta" ); // Insert a row for each of these names.
System.out.println( "Inserting list of names: " + names );
try (
PreparedStatement ps = conn.prepareStatement( sql ) ;
) {
for ( String name : names ) {
ps.setString( 1 , name );
ps.executeUpdate();
}
}
// Retrieve rows from a `ResultSet`.
sql = "SELECT * FROM " + "guild_" + " ;";
try (
Statement stmt = conn.createStatement() ;
ResultSet rs = stmt.executeQuery( sql ) ;
) {
while ( rs.next() ) {
UUID pkey = rs.getObject( "pkey_" , UUID.class );
String name = rs.getString( "name_" );
System.out.println( "Row pkey_: " + pkey + " name_: " + name );
}
}
} catch ( SQLException e ) {
e.printStackTrace();
}
}
}
When run.
Inserting list of names: [Alpha, Beta, Gamma, Delta]
Row pkey_: 69908390-5fa6-4eee-8e12-40106db8d60d name_: Alpha
Row pkey_: 3116acb9-fcce-427f-b222-99c78c6e752a name_: Beta
Row pkey_: b3fd0930-a2e7-461a-be70-f05124fc58de name_: Gamma
Row pkey_: dddb423a-5eb2-4e5e-be16-7bb0c27c0033 name_: Delta
This question already has answers here:
Is there a way to retrieve the autoincrement ID from a prepared statement
(5 answers)
Closed 7 years ago.
I have this code trying to insert a record in the database:
try {
Connection conn = getConnection();
String sql =
"INSERT INTO myTable(userId,content,timestamp) VALUES(?,?,NOW())";
PreparedStatement st =
conn.prepareStatement(sql,Statement.RETURN_GENERATED_KEYS);
st.setLong(1, userId);
st.setString(2, content);
id = st.executeUpdate(); //this is the problem line
} catch(Exception e) {}
The problem is, though the record is inserted correctly, I want id to contain the primary key + auto_increment id of the record that was just inserted. However, for some reason, it always returns '1' as the id, possibly because the value of userId is 1 during the inserts.
My table is InnoDB. At first userId was a foreign key to another table, owever I've since deleted the foreign key and even the index on the userId column, but I'm still getting 1 as the return value.
Any ideas what I'm doing wrong?
PreparedStatment.executeUpdate()
Returns:
either (1) the row count for SQL Data Manipulation Language (DML) statements or (2) 0 for SQL statements that return nothing
You need to use execute() instead and get the ResultSet with getGeneratedKeys(); it's going to contain the data you want.
Edit to add: I read your question as there is an auto-increment field in the table that is not userId
The accepted Answer by Brian Roach is correct. I'm adding some thoughts and an example with full code.
RETURN_GENERATED_KEYS Does Not Mean “return generated keys”
The original poster seems to be confused, understandably, by the phrasing of the flag Statement.RETURN_GENERATED_KEYS. Contrary to intuition, passing this flag does not change the behavior of the PreparedStatement::executeUpdate method. That method always returns an int, the number of rows affected by the SQL executed. The "executeUpdate" method never returns the generated keys.
int countRowsAffected = pstmt.executeUpdate(); // Always return number of rows affected, *not* the generated keys.
Ask, and Ye Shall Receive
If you want the generated keys, you must do two steps:
Pass the flag, and
Ask for a ResultSet made up of rows containing only the generated key values.
This arrangement allows you to add the behavior of getting back generated keys while keeping the other desirable behavior, getting a count of the number of rows affected.
Example Code
Here is a nearly real-world example taken from a Java 8 app that scrapes data from a data feed. I think in this context a full-blown example may be more useful than a minimal one.
Minor details… This code may not be perfect, syntactically or otherwise, as I copy-pasted-modified real source code. I am using the UUID data type rather than integers as the surrogate primary key of my table. The classes CharHelper and DBHelper are my own, the details of which are not important here. The x and y variables are replacements of my own app's meaningful data. My logging calls are made to the SLF4J framework. The UUID hex strings are a convenient way to link reports in the logs back to the original source code. The database is Postgres, but this kind of code should work on any database supporting the reporting of generating keys.
public UUID dbWrite ( String x , String y , DateTime whenRetrievedArg ) {
if ( whenRetrievedArg == null ) {
logger.error( "Passed null for whenRetrievedArg. Message # 2112ed1a-4612-4d5d-8cc5-bf27087a350d." );
return null;
}
Boolean rowInsertComplete = Boolean.FALSE; // Might be used for debugging or logging or some logic in other copy-pasted methods.
String method = "Method 'dbWrite'";
String message = "Insert row for some_table_ in " + method + ". Message # edbea872-d3ed-489c-94e8-106a8e3b58f7.";
this.logger.trace( message );
String tableName = "some_table_";
java.sql.Timestamp tsWhenRetrieved = new java.sql.Timestamp( whenRetrievedArg.getMillis() ); // Convert Joda-Time DatTime object to a java.sql.Timestamp object.
UUID uuidNew = null;
StringBuilder sql = new StringBuilder( AbstractPersister.INITIAL_CAPACITY_OF_SQL_STRING ); // private final static Integer INITIAL_CAPACITY_OF_SQL_STRING = 1024;
sql.append( "INSERT INTO " ).append( tableName ).append( CharHelper.CHAR.PAREN_OPEN_SPACED ).append( " x_ , y_ " ).append( CharHelper.CHAR.PAREN_CLOSED ).append( DBHelper.SQL_NEWLINE );
sql.append( "VALUES ( ? , ? , ? ) " ).append( DBHelper.SQL_NEWLINE );
sql.append( ";" );
try ( Connection conn = DBHelper.instance().dataSource().getConnection() ;
Here we do Step # 1, pass the RETURN_GENERATED_KEYS flag.
PreparedStatement pstmt = conn.prepareStatement( sql.toString() , Statement.RETURN_GENERATED_KEYS ); ) {
We continue to prepare and execute the statement. Note that int countRows = pstmt.executeUpdate(); returns the count of affected rows, not the generated keys.
pstmt.setString( 1 , x );
pstmt.setString( 2 , y );
pstmt.setTimestamp( 3 , tsWhenRetrieved );
// Execute
int countRows = pstmt.executeUpdate(); // Always returns an int, a count of affected rows. Does *not* return the generated keys.
if ( countRows == 0 ) { // Bad.
this.logger.error( "Insert into database for new " + tableName + " failed to affect any rows. Message # 67e8de7e-67a5-42a6-a4fc-06929211e6e3." );
} else if ( countRows == 1 ) { // Good.
rowInsertComplete = Boolean.TRUE;
} else if ( countRows > 1 ) { // Bad.
rowInsertComplete = Boolean.TRUE;
this.logger.error( "Insert into database for new " + tableName + " failed, affecting more than one row. Should not be possible. Message # a366e215-6cf2-4e5c-8443-0b5d537cbd68." );
} else { // Impossible.
this.logger.error( "Should never reach this Case-Else with countRows value " + countRows + " Message # 48af80d4-6f50-4c52-8ea8-98856873f3bb." );
}
Here we do Step # 2, ask for a ResultSet of the generated keys. In the case of this example, we inserted a single row and expect back a single generated key.
if ( rowInsertComplete ) {
// Return new row’s primary key value.
ResultSet genKeys = pstmt.getGeneratedKeys();
if ( genKeys.next() ) {
uuidNew = ( UUID ) genKeys.getObject( 1 ); // ResultSet should have exactly one column, the primary key of INSERT table.
} else {
logger.error( "Failed to get a generated key returned from database INSERT. Message # 6426843e-30b6-4237-b110-ec93faf7537d." );
}
}
The rest is error-handling and clean-up. Do note that we return the UUID, the generated primary key of the inserted record, at the bottom of this code.
} catch ( SQLException ex ) {
// We expect to have occasional violations of unique constraint on this table in this data-scraping app.
String sqlState = ex.getSQLState();
if ( sqlState.equals( DBHelper.SQL_STATE.POSTGRES.UNIQUE_CONSTRAINT_VIOLATION ) ) { // SqlState code '23505' = 'unique_violation'.
this.logger.trace( "Found existing row when inserting a '" + tableName + "' row for y: " + y + ". Expected to happen on most attempts. Message # 0131e8aa-0bf6-4d19-b1b3-2ed9d333df27." );
return null; // Bail out.
} else { // Else any other exception, throw it.
this.logger.error( "SQLException during: " + method + " for table: " + tableName + ", for y: " + y + ". Message # 67908d00-2a5f-4e4e-815c-5e5a480d614b.\n" + ex );
return null; // Bail out.
}
} catch ( Exception ex ) {
this.logger.error( "Exception during: " + method + " for table: " + tableName + ", for y: " + y + ". Message # eecc25d8-de38-458a-bb46-bd6f33117969.\n" + ex );
return null; // Bail out.
}
if ( uuidNew == null ) {
logger.error( "Returning a null uuidNew var. SQL: {} \nMessage # 92e2374b-8095-4557-a4ed-291652c210ae." , sql );
}
return uuidNew;
}
String SQLQuery=" ";
String generatedKeys[]= {"column_name"};//'column_name' auto-increment column
prepSt = Connection.prepareStatement(SQLQuery,generatedKeys);
prepSt.setInt(1, 1234);
.....
.....
....
prepSt.executeUpdate();
ResultSet rs = prepSt.getGeneratedKeys; // used same PreparedStatement object as used for Insert .
if(rs.next()) {
int id=rs.getLong("column_name");
System.out.println(id);
}
} catch (SQLException e) {
}
If you have set userId has auto-increment in your database, you shouldn't try and add it yourself. You should insert NULL, and it will auto-increment for you! (The clue is in the name!)
Also, you are not updating your table, you are inserting into it. So you don't executeUpdate(). Try...
PreparedStatement pst = conn.prepareStatement("INSERT INTO myTable(userId,content,timestamp) VALUES(NULL,?,NOW())");
pst.setString(1, content);
pst.executeQuery();
What you get is the notification of 'Rows insetrted' (for INSERT statement). We use this method to know whether our DML query is succesful or not. The following is the way to get the Auto generated ID using [prepareStatement(yourSQL, Statement.RETURN_GENERATED_KEYS)]. Pls note that this method only return you a RowID ref. To get the actual val, pls refer to Method 2.
(Method 1)
Try{
String yourSQL="insert into Table1(Id,Col2,Col3) values(SEQ.nextval,?,?)";
myPrepStatement = <Connection>.prepareStatement(yourSQL, Statement.RETURN_GENERATED_KEYS);
myPrepStatement.setInt(1, 123);
myPrepStatement.setInt(2, 123);
myPrepStatement.executeUpdate();
ResultSet rs = getGeneratedKeys;
if(rs.next()) {
java.sql.RowId rid=rs.getRowId(1);
//what you get is only a RowId ref, try make use of it anyway U could think of
System.out.println(rid);
}
} catch (SQLException e) {
}
(Method 2)
Try{
String yourSQL="insert into Table1(Id,Col2,Col3) values(SEQ.nextval,?,?)";
//IMPORTANT: here's where other threads don tell U, you need to list ALL cols
//mentioned in your query in the array
myPrepStatement = <Connection>.prepareStatement(yourSQL, new String[]{"Id","Col2","Col3"});
myPrepStatement.setInt(1, 123);
myPrepStatement.setInt(2, 123);
myPrepStatement.executeUpdate();
ResultSet rs = getGeneratedKeys;
if(rs.next()) {
//In this exp, the autoKey val is in 1st col
int id=rs.getLong(1);
//now this's a real value of col Id
System.out.println(id);
}
} catch (SQLException e) {
}
Basically, try not used Method1 if you just want the value of SEQ.Nextval, b'cse it just return the RowID ref that you may cracked your head finding way to make use of it, which also don fit all data type you tried casting it to! This may works fine (return actual val) in MySQL, DB2 but not in Oracle.
IMPORTANT:
Turn off your SQL Developer, Toad or any client which use the same login session to do INSERT when you're debugging. It MAY not affect you every time (debugging call) ... until you find your apps freeze without exception for some time. Yes ... halt without exception!
I have a table where I have to do a SELECT ... BETWEEN start_date AND end_date, as well as insert Date values into the same table.
I read things like:
java.util.Date now = new java.util.Date();
pStmt.setDate( 1, new java.sql.Date( now.getTime() ) );
pStmt.setTimestamp( 2, new java.sql.Timestamp( now.getTime() ) );
pStmt.executeUpdate();
But that kind of code sets or gets the current date, doesn't it? I want to insert and select custom dates myself.
I also read it here at StackOverflow:
SELECT *
FROM myTable
WHERE ( YEAR(myfield) = '2009')
AND ( MONTH(myfield) = '1')
Is it also possible to make the Date fields String, then use StringTokenizer to extract only the day, month or year information and use them in a SELECT similar to this code? (In case my first - and simpler - idea is impossible.)
So until now, there's two possible solutions. I also need to know which one is faster since the database accessed is in a fail-safe / critical system (a bank) with lots of data.
The first approach is better, because you were able to use date functions to manipulate values.
private void executeQuery(java.util.Date startDate, java.util.Date endDate) throws SQLException {
Connection conn = null;
PreparedStatement pstmt = null;
try {
conn = getConnection();
String query = "select ... between ? and ?";
pstmt = conn.prepareStatement(query);
pstmt.setDate(1, new java.sql.Date(startDate.getTime()));
pstmt.setDate(2, new java.sql.Date(endDate.getTime()));
//return results
ResultSet rs = pstmt.executeQuery();
rs.last();
System.out.println("last row = " + rs.getRow());
} finally {
if (pstmt != null) {
pstmt.close();
}
if (conn != null) {
conn.close();
}
}
}