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

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

【问题讨论】:

  • 从一开始就试图获取这个值是一种糟糕的设计模式。你想完成什么?

标签: android sqlite auto-increment


【解决方案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();
                    }
        

        【讨论】:

          猜你喜欢
          • 2016-09-22
          • 1970-01-01
          • 2015-08-28
          • 1970-01-01
          • 2019-09-23
          • 2011-05-16
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多