获取 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 从最大值递增。 在尝试之前,我们必须检查是否有任何行被插入到这个表中,如果我们没有返回一些常量 idcursor.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检查一行中的值是不是在没有循环的下一行中的值之间