如何使用 SQLite3 获取 jdbc 中最后插入的 ID?

How to get the last inserted id in jdbc with SQLite3?

所以我在学校的一个项目中工作,现在我完全陷入困境。我只需要这一件事就可以了,我已经完成了。

问题描述

我的问题是获取我插入数据库的最后一件事的 id

最小示例

下载 sqlite-jdbc-3.36.0.3,并将其放在您当前的工作目录中。请确保您没有 temp.sql 文件(在程序 运行s 之后删除它)。

创建一个名为 Main.java 的文件,内容如下:

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;
    }
}

然后试试代码:

  1. 编译它。 (javac Main.java)
  2. 删除 temp.sql 如果存在
  3. 运行吧。 (java -cp "./sqlite-jdbc-3.36.0.3.jar;." Main)

如果有人在 windows 中使用 powershell,我使用的是:

javac .\Main.java; rm .\temp.sql; java -cp ".\sqlite-jdbc-3.36.0.3.jar;." Main

我尝试了什么?

1) last_insert_rowid()

我在网上看到 last_insert_rowid() 会 return 你在 SQLite 中插入的最后一个东西的 id,所以我这样做了:

final Integer id =
    exec("SELECT last_insert_rowid()", conn).getUpdateCount();

System.out.println("The last inserted id is " + id);

然后我得到结果:

The last inserted id is -1

如我所料:

The last inserted id is 1

而且我知道预期结果是正确的,因为如果我 运行:

sqlite3.exe .\temp.sql "SELECT * FROM temp"

输出是:

1|340975

2) SELECT MAX(id) FROM ...

我知道最后插入的 id 将始终是 table 中最大的 id(除非 table 具有并且 id 是它可以容纳的最大值,但这将在我的应用程序中从来没有这种情况,source),所以我尝试了这个:

final Integer id =
    exec("SELECT MAX(id) FROM temp", conn).getUpdateCount();

System.out.println("The last inserted id is " + id);

我得到了与 last_insert_rowid() 相同的输出。

并尝试:

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

我得到:

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)

我已经有一段时间没有使用 sqlite 了,但这对我来说是错误的: id = exec("SELECT last_insert_rowid()", conn).getUpdateCount(); 您没有更新任何内容,因此不会有更新计数。

不应该是这样的吗?

ResultSet rs = conn.prepareStatement("select last_insert_rowid();").executeQuery();

执行查询是为了选择,可以return一个结果集。它不同于用数据更新数据库。

所以在写问题的时候我找到了答案。但是既然已经写完了,我想我会分享答案,希望对以后的人有所帮助。

final Integer id =
    exec("SELECT last_insert_rowid()", conn).getUpdateCount();

System.out.println("The last inserted id is " + id);

错了,正确的做法是:

ResultSet rs =
    exec("SELECT last_insert_rowid()", conn).getResultSet();

if (!rs.next()) {
    System.out.println("Something is wrong...");
    return;
}

final Integer id = rs.getInt("last_insert_rowid()");
System.out.println("The last inserted id is " + id);

对于SELECT MAX ...的做法,正确的取值方式是:

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("MAX(id)");
System.out.println("The last inserted id is " + id);

函数last_insert_rowid()returns:

the ROWID of the last row insert from the database connection which invoked the function

因此,如果您关闭了上次插入所用的连接并 运行 使用另一个连接进行查询,您将不会获得插入的最后一行的 rowid
此外,如果您的数据库中有多个 table,并且您使用相同的连接在其中的多个中插入,则必须在每个 table 中的最后一次插入之后调用 last_insert_rowid()获取每个 table.

中插入的最后一行的 rowid

当您在查询中使用 MAX(id) 并且 id 定义为 INTEGER PRIMARY KEY 时,您将获得 table 和 [=49] 的最大值 id =]不一定插入最后一行的rowidbecause:

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.

确保 MAX(id) 将 return 插入最后一行的 rowid 的唯一方法是,如果您使用关键字 [=26] 定义了 id =] 还有:

id INTEGER PRIMARY KEY AUTOINCREMENT

因为在这种情况下:

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.

最后,通常的做法是通过名称或别名来引用列,而不是:

SELECT MAX(id) FROM temp

你应该使用:

SELECT MAX(id) AS max_id FROM temp

以便您可以通过别名 max_id:

访问查询结果
final Integer id = rs.getInt("max_id");