Sqlite中的rowid字段和integer primary key autoincrement的字段区别

前言

原创文章,欢迎转载,请保留出处。
有任何错误、疑问或者建议,欢迎指出。
我的邮箱:[email protected]

Android中提供的SQLiteDatabase类,其中的几个方法返回的是rowid,这个rowid并不是插入的行号(row num或者说是RecNo),而是sqlite中自动维护的一个隐藏的列rowid,这个rowid和integer primary key autoincrement的字段有什么区别呢?

Android中的数据库查询API

我们以Android中提供的数据库插入API:db.insert来说明,这个方法的返回值描述如下:

Returns:
the row ID of the newly inserted row, or -1 if an error occurred

经过验证,这里的row ID是是rowid,并不是插入的行号(row num或者说是RecNo)。下面我们假设integer primary key autoincrement的字段的字段名为id,如下图:
返回的是rowid

RecNo和id:

RecNo和id

rowid和id:

rowid和id

但是这个rowid属于由sqlite自己维护的列,如果不显式指定,即使使用select * from table也是不会出现的。
如果要查询rowid必须使用select rowid,* from table

RecNo和id区别

这个比较简单,RecNo是单调递增,无论数据表怎么变化,只要查询结果的第一条就是1(表头为0),当然这个和表没有任何关系,如果order by是由用户决定的,所以不存在对应关系。
而id也是单调递增的,如果删除了某一条记录,id还是会继续递增,不会调整,id属于数据表的字段,和数据有对应关系,无论怎么查询,id都不会变化。
比如select rowid,* from table order by id desc结果:
查询结果
结论:RecNo就是查询结果的一个标号而已。

rowid和id区别

这个rowid和每条数据是有密切关系的
比如select rowid,* from table order by id desc结果:
查询结果

我们参考sqlite官网提供说明:

https://www.sqlite.org/autoinc.html

The AUTOINCREMENT Keyword

If a column has the type INTEGER PRIMARY KEY AUTOINCREMENT then a slightly different ROWID selection algorithm is used. 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. If the table has previously held a row with the largest possible ROWID, then new INSERTs are not allowed and any attempt to insert a new row will fail with an SQLITE_FULL error. Only ROWID values from previously transactions that were committed are considered. ROWID values that were rolled back are ignored and can be reused.

SQLite keeps track of the largest ROWID that a table has ever held 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. The content of the sqlite_sequence table can be modified using ordinary UPDATE, INSERT, and DELETE statements. But making modifications to this table will likely perturb the AUTOINCREMENT key generation algorithm. Make sure you know what you are doing before you undertake such changes.

The behavior implemented by the AUTOINCREMENT keyword is subtly different from the default behavior. With AUTOINCREMENT, rows with automatically selected ROWIDs are guaranteed to have ROWIDs that have never been used before by the same table in the same database. And the automatically generated ROWIDs are guaranteed to be monotonically increasing. These are important properties in certain applications. But if your application does not need these properties, you should probably stay with the default behavior since the use of AUTOINCREMENT requires additional work to be done as each row is inserted and thus causes INSERTs to run a little slower.

Note that “monotonically increasing” does not imply that the ROWID always increases by exactly one. One is the usual increment. However, if an insert fails due to (for example) a uniqueness constraint, the ROWID of the failed insertion attempt might not be reused on subsequent inserts, resulting in gaps in the ROWID sequence. AUTOINCREMENT guarantees that automatically chosen ROWIDs will be increasing but not that they will be sequential.

Because AUTOINCREMENT keyword changes the behavior of the ROWID selection algorithm, AUTOINCREMENT is not allowed on WITHOUT ROWID tables or on any table column other than INTEGER PRIMARY KEY. Any attempt to use AUTOINCREMENT on a WITHOUT ROWID table or on a column other than the INTEGER PRIMARY KEY column results in an error.

简单抽取关键的内容就是:id如果设置为integer primary key autoincrement的字段,则不需要自己手动赋值,插入时传入null由数据库来设置其值,这个值数据库默认设置为rowid的最大值+1(也可以自己手动设置,但不要引起重复等问题)
rowid:单调递增,直到达到最大值后,复用已经删除的rowid作为新的值
id:可以自行设置,或者是数据库自动设置(rowid的最大值+1),到达最大值后不复用已经删除的值,抛异常SQLITE_FULL 。

这里可以得出结论:rowid和id不一样,不要混用。

特殊情况

如果integer primary key autoincrement的字段名为rowid,那么怎么查询rowid?
答案是相同的方法,rowid不是存在表中的,而是在sqlite_sequence中,如果查询,则自己设置的rowid会起别名:
查询结果

不查询rowid则不会起别名:

查询结果

你可能感兴趣的:(android开发,数据库)