So im working in a proyect from school, and now im completely stuck. I just need this one thing to work and Im done.
My problem is to get the id
of the last thing I inserted in the database.
Download sqlite-jdbc-3.36.0.3, and have it in your current working directory. Make sure that you dont have a temp.sql
file in it (Delete it after the program runs).
Create a file named Main.java
with the following contents:
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class Main {
public static final String createDbQuery =
"CREATE TABLE temp (\n"
+ "id integer PRIMARY KEY,\n"
+ "data integer\n"
+")";
// In the actual code im using a proper PreparedStatement, but I will keep
// is simple here
public static final String insertSomethingQuery =
"INSERT INTO temp (data) VALUES (340975)";
public static void main(String[] args) {
Connection conn = null;
try {
conn = connect();
exec(createDbQuery, conn);
exec(insertSomethingQuery, conn);
/*
* Try here the code that will be mentioned in the rest of the
* question
*/
} catch (final Exception e) {
e.printStackTrace();
} finally {
if (conn != null) {
disconect(conn);
}
}
}
public static Connection connect() throws SQLException {
return DriverManager.getConnection("jdbc:sqlite:temp.sql");
}
public static void disconect(Connection conn) {
try {
conn.close();
} catch (final SQLException e) {
e.printStackTrace();
}
}
public static Statement exec(String query, Connection conn)
throws SQLException {
Statement s = conn.createStatement();
s.execute(query);
return s;
}
}
Then to try the code:
javac Main.java
)temp.sql
if it existsjava -cp "./sqlite-jdbc-3.36.0.3.jar;." Main
)If someone is using powershell in windows, im using this:
javac .\Main.java; rm .\temp.sql; java -cp ".\sqlite-jdbc-3.36.0.3.jar;." Main
last_insert_rowid()
I saw on the internet that last_insert_rowid()
will return the id of the last thing you inserted in SQLite, so I did this:
final Integer id =
exec("SELECT last_insert_rowid()", conn).getUpdateCount();
System.out.println("The last inserted id is " + id);
Then I get the result:
The last inserted id is -1
When I expected:
The last inserted id is 1
And I know that the expected result is correct because if I run:
sqlite3.exe .\temp.sql "SELECT * FROM temp"
The ouput is:
1|340975
SELECT MAX(id) FROM ...
I know that the last inserted id will always be the biggest id in the table (except if the table has and id that is the maximum values that it can hold, but that will never be the case in my app, source), so I tried this:
final Integer id =
exec("SELECT MAX(id) FROM temp", conn).getUpdateCount();
System.out.println("The last inserted id is " + id);
And I got the same output as with last_insert_rowid()
.
And trying with:
ResultSet rs =
exec("SELECT MAX(id) FROM temp", conn).getResultSet();
if (!rs.next()) {
System.out.println("Something is wrong...");
return;
}
final Integer id = rs.getInt("id");
System.out.println("The last inserted id is " + id);
I get:
java.sql.SQLException: no such column: 'id'
at org.sqlite.jdbc3.JDBC3ResultSet.findColumn(JDBC3ResultSet.java:49)
at org.sqlite.jdbc3.JDBC3ResultSet.getInt(JDBC3ResultSet.java:402)
at Main.main(Main.java:37)
The function last_insert_rowid()
returns:
the ROWID of the last row insert from the database connection which invoked the function
So, if you closed the connection with which you did the last insertion and run the query with another connection you will not get the rowid
of the last row inserted.
Also if there are multiple tables in your database and you do insertions in more than 1 of them with the same connection, you will have to call last_insert_rowid()
after the last insertion in each table to get the rowid
of the last row inserted in each table.
When you use MAX(id)
in a query and id
is defined as INTEGER PRIMARY KEY
you get the max id
of the table and not necessarily the rowid
of the last row inserted, because:
If you ever delete rows or if you ever create a row with the maximum possible ROWID, then ROWIDs from previously deleted rows might be reused when creating new rows and newly created ROWIDs might not be in strictly ascending order.
The only way to be sure that MAX(id)
will return the rowid
of the last row inserted is if you have defined id
with the keyword AUTOINCREMENT
also:
id INTEGER PRIMARY KEY AUTOINCREMENT
because in this case:
The ROWID chosen for the new row is at least one larger than the largest ROWID that has ever before existed in that same table. If the table has never before contained any data, then a ROWID of 1 is used.
Finally, it is common practice to refer to columns by their names or aliases, so instead of:
SELECT MAX(id) FROM temp
you should use:
SELECT MAX(id) AS max_id FROM temp
so that you can access the result of the query by the alias max_id
:
final Integer id = rs.getInt("max_id");