获取 SQLite 数据库的下一个 AUTO_INCREMENT 值

Posted

技术标签:

【中文标题】获取 SQLite 数据库的下一个 AUTO_INCREMENT 值【英文标题】:Getting the next AUTO_INCREMENT value of a SQLite database 【发布时间】:2011-10-20 11:55:23 【问题描述】:

使用 android API 中的典型 SQLiteDatabase 对象,我可以做些什么来获取特定列的下一个 AUTO_INCREMENT 值(即id)而不影响值本身。有没有办法呢?或者我应该执行什么查询来获得该结果。请记住,SQLiteDatabase.query() 返回一个 Cursor 对象,所以如果我只想从中获取一个值,我不太确定如何直接处理它。

【问题讨论】:

从一开始就试图获取这个值是一种糟糕的设计模式。你想完成什么? 【参考方案1】:

你是对的。第一个答案(仍在下方)仅适用于没有 AUTOINCREMENT 的 id。使用 AUTOINCREMENT,值存储在单独的表中并用于增量。这是一个查找值的示例:

public void printAutoIncrements()
    String query = "SELECT * FROM SQLITE_SEQUENCE";
    Cursor cursor = mDb.rawQuery(query, null);
    if (cursor.moveToFirst())
        do
            System.out.println("tableName: " +cursor.getString(cursor.getColumnIndex("name")));
            System.out.println("autoInc: " + cursor.getString(cursor.getColumnIndex("seq")));

        while (cursor.moveToNext());
    

    cursor.close(); 


见:http://www.sqlite.org/autoinc.html

第一个答案:

可以查询_id列的最大值,如:

String query = "SELECT MAX(id) AS max_id FROM mytable";
Cursor cursor = db.rawQuery(query, null);

int id = 0;     
if (cursor.moveToFirst())

    do
               
        id = cursor.getInt(0);                  
     while(cursor.moveToNext());           

return id;

这适用于尚未指定为“INTEGER PRIMARY KEY AUTOINCREMENT”的行 ID(所有表都有一个行 ID 列)。

【讨论】:

表的最大 id 不一定是 AUTO_INCREMENT 值,因为如果删除了具有更高 id 的行怎么办?获取最大 id 是不正确的。 @aha 您显然可以使用 cursor.getCount() 并递增其值并将其存储为自动递增值....... @hanry cursor.getCount() 很可能每次都是错误的方法:任何时候从表中删除一行。对于没有自动递增行 id 的表,默认行 id 从最大值递增。 在尝试之前,我们必须检查是否有任何行被插入到这个表中,如果我们没有返回一些常量 id cursor.moveToFirst() 为假【参考方案2】:

这是在使用 SQLITE 自动递增 PRIMARY KEY 时获取最后一个 ID 的最佳方法

String query = "select seq from sqlite_sequence WHERE name = 'Table_Name'"

【讨论】:

【参考方案3】:

关于 SQLITE_SEQUENCE 表的重要说明。

文档说

每当创建包含 AUTOINCREMENT 列的普通表时,都会自动创建和初始化 SQLITE_SEQUENCE 表。

因此创建了 SQLITE_SEQUENCE 表,但未创建与包含 AUTOINCREMENT 列的表关联的行。该行是使用第一个插入查询创建的(“seq”值为 1)。

这意味着在查找特定表的下一个自动增量值之前,您必须至少执行一次插入操作。例如,可以在创建表之后执行虚拟行的插入和删除。

【讨论】:

是的,我们只需要在尝试获取下一个增量值之前检查是否可以 moveToFirst 或 getCount 【参考方案4】:

这是我用来获取特定表的下一个 AUTOINCREMENT 值的方法:

/**
 * Query sqlite_sequence table and search for the AUTOINCREMENT value for <code>tableName</code>
 * @param tableName The table name with which the AUTOINCREMENT value is associated.
 *
 * @return The next AUTOINCREMENT value for <code>tableName</code>
 * If an INSERT call was not previously executed on <code>tableName</code>, the value 1 will
 * be returned. Otherwise, the returned value will be the next AUTOINCREMENT.
 */
private long getNextAutoIncrement(String tableName) 
    /*
     * From the docs:
     * SQLite keeps track of the largest ROWID using an internal table named "sqlite_sequence".
     * The sqlite_sequence table is created and initialized automatically
     * whenever a normal table that contains an AUTOINCREMENT column is created.
     */
    String sqliteSequenceTableName = "sqlite_sequence";
    /*
     * Relevant columns to retrieve from <code>sqliteSequenceTableName</code>
     */
    String[] columns = "seq";
    String selection = "name=?";
    String[] selectionArgs =  tableName ;

    Cursor cursor = mWritableDB.query(sqliteSequenceTableName, 
            columns, selection, selectionArgs, null, null, null);

    long autoIncrement = 0;

    if (cursor.moveToFirst()) 
        int indexSeq = cursor.getColumnIndex(columns[0]);
        autoIncrement = cursor.getLong(indexSeq);
    

    cursor.close();

    return autoIncrement + 1;

【讨论】:

只是想知道,如果您插入一条 ID = 'autoIncrement + 1' 的记录,然后插入一条记录而不指定 ID 会发生什么?例如:序列 = 9,在这种情况下返回 10 并插入 ID = 10(指定)的记录。然后,您插入一条新记录而不指定 ID。 SQLite 是否知道他必须为 ID 插入 11 ?还是他会尝试插入 10 并导致错误?【参考方案5】:

在您使用的 SQLiteOpenHelper 中,启动一个事务。插入一些数据,然后回滚。

这样一来,你就可以得到下一行的id,像这样:

public long nextId() 
    long rowId = -1;

    SQLiteDatabase db = getWritableDatabase();
    db.beginTransaction();
    try 
        ContentValues values = new ContentValues();
        // fill values ...

        // insert a valid row into your table
        rowId = db.insert(TABLE_NAME, null, values);

        // NOTE: we don't call  db.setTransactionSuccessful()
        // so as to rollback and cancel the last changes
     finally 
        db.endTransaction();
    
    return rowId;

【讨论】:

【参考方案6】:

成功了。

public static long getNextId(SQLiteDatabase db, String tableName) 
    Cursor c = null;
    long seq = 0;
    try 
        String sql = "select seq from sqlite_sequence where name=?";
        c = db.rawQuery(sql, new String[] tableName);
        if (c.moveToFirst()) 
            seq = c.getLong(0);
        
     finally 
        if (c != null) 
            c.close();
        
    
    return seq + 1;

【讨论】:

【参考方案7】:

你可以使用cursor.getInt(i);方法i这里是id列的索引

Cursor c = db.rawQuery("Select * From mSignUp", null);
            String mail = null;
            try 
                while (c.moveToNext()) 
                    mail = c.getString(0);
                    String pas = c.getString(1);
                    Toast.makeText(getApplicationContext(), "Name = " + mail + " Pass = " + pas, Toast.LENGTH_SHORT).show();
                
            catch (CursorIndexOutOfBoundsException e)
                Log.e("OutOfBound", Log.getStackTraceString(e));
            
            finally 
                c.close();
            

【讨论】:

以上是关于获取 SQLite 数据库的下一个 AUTO_INCREMENT 值的主要内容,如果未能解决你的问题,请参考以下文章

从 API 获取 JSON,将其添加到 sqlite3 数据库并自动获取下一页

Sqlite检查一行中的值是不是在没有循环的下一行中的值之间

eclipse-android开发过程中,将sqlite字段原值手工修改后,无法查询到关联的下一个表

使用 PDO 创建新的 SQLite DB

通过查询计算 SQLiteDB 的下四分位数和上四分位数

iCloud 中基于 SQLite 的核心数据中的有序关系