最近由于sqlite數(shù)據(jù)庫操作不當出了一些問題凛俱,主要是由于升級導致的,具體原因不說了薄腻,總結(jié)一下在這次修復過程中總結(jié)的sqlite相關(guān)的知識點岛马。
1棉姐、版本號
SQLiteDatabase#getVersion方法,since API 1
getVersion其實是執(zhí)行了一句命令PRAGMA user_version命令啦逆。
將一個sqlite數(shù)據(jù)庫拖到SQLite Expert Personal打開伞矩,首先看到的是關(guān)于該數(shù)據(jù)庫的一系列基本狀態(tài):
在SQL中執(zhí)行PRAGMA user_version命令可以拿到user_version值
PRAGMA是一個特殊的命令,可以在SQLite環(huán)境中控制(讀寫)各種環(huán)境變量和狀態(tài)標志夏志,語法:
PRAGMA pragma_name;
PRAGMA pragma_name = value;
2乃坤、當前數(shù)據(jù)庫版本與SQLiteOpenHelper打開的版本不同會發(fā)生什么?
如果發(fā)現(xiàn)希望打開的數(shù)據(jù)庫版本比現(xiàn)有的數(shù)據(jù)庫版本高,則會先進行數(shù)據(jù)庫升級操作湿诊;反之則進行降級操作狱杰。
3、數(shù)據(jù)庫升級降級在Android3.0之后的改變
在Android 3.0(API 11)之前厅须,如果版本號有改變浦旱,無論是升級降級,均回調(diào)onUpgrade方法九杂;
而從Android3.0開始及以后版本,區(qū)分升級和降級宣蠕;其中例隆,onDowngrade方法也是在Android3.0之后才有的,如果是降級抢蚀,則必須復寫該方法镀层,否則將會拋出SQLiteException異常。
Android 2.2.3源碼 SQLiteOpenHelper.java
public synchronized SQLiteDatabase getWritableDatabase() {
...
try {
...
int version = db.getVersion();
if (version != mNewVersion) {
db.beginTransaction();
try {
if (version == 0) {
onCreate(db);
} else {
onUpgrade(db, version, mNewVersion);
}
db.setVersion(mNewVersion);
db.setTransactionSuccessful();
} finally {
db.endTransaction();
}
}
...
}
Android 5.1.1源碼 SQLiteOpenHelper.java
private SQLiteDatabase getDatabaseLocked(boolean writable) {
....
final int version = db.getVersion();
if (version != mNewVersion) {
if (db.isReadOnly()) {
throw new SQLiteException("Can't upgrade read-only database from version " +
db.getVersion() + " to " + mNewVersion + ": " + mName);
}
db.beginTransaction();
try {
if (version == 0) {
onCreate(db);
} else {
if (version > mNewVersion) {
onDowngrade(db, version, mNewVersion);
} else {
onUpgrade(db, version, mNewVersion);
}
}
...
}
onOpen(db);
...
}
4皿曲、遍歷數(shù)據(jù)庫中的表
Cursor cursor = db.rawQuery("select name from sqlite_master where type='table';", null);
while(cursor.moveToNext()){
//遍歷出表名
String name = cursor.getString(0);
Log.i("System.out", name);
}
SQLite數(shù)據(jù)庫中一個特殊的名叫 SQLITE_MASTER 上執(zhí)行一個SELECT查詢以獲得所有表的索引唱逢。每一個 SQLite 數(shù)據(jù)庫都有一個叫 SQLITE_MASTER 的表, 它定義數(shù)據(jù)庫的模式屋休。 SQLITE_MASTER 表看起來如下:
CREATE TABLE sqlite_master (
type TEXT,
name TEXT,
tbl_name TEXT,
rootpage INTEGER,
sql TEXT
);
對于表來說坞古,type 字段永遠是 ‘table’,name 字段永遠是表的名字劫樟。所以痪枫,要獲得數(shù)據(jù)庫中所有表的列表, 使用下列SELECT語句:
SELECT name FROM sqlite_master
WHERE type=’table’
ORDER BY name;
對于索引叠艳,type 等于 ‘index’, name 則是索引的名字奶陈,tbl_name 是該索引所屬的表的名字。 不管是表還是索引附较,sql 字段是原先用 CREATE TABLE 或 CREATE INDEX 語句創(chuàng)建它們時的命令文本。對于自動創(chuàng)建的索引(用來實現(xiàn) PRIMARY KEY 或 UNIQUE 約束),sql字段為NULL逾滥。
SQLITE_MASTER 表是只讀的羡儿。不能對它使用 UPDATE、INSERT 或 DELETE捕发。 它會被 CREATE TABLE疏旨、CREATE INDEX、DROP TABLE 和 DROP INDEX 命令自動更新扎酷。
臨時表不會出現(xiàn)在 SQLITE_MASTER 表中檐涝。臨時表及其索引和觸發(fā)器存放在另外一個叫 SQLITE_TEMP_MASTER 的表中。SQLITE_TEMP_MASTER 跟 SQLITE_MASTER 差不多, 但它只是對于創(chuàng)建那些臨時表的應(yīng)用可見谁榜。如果要獲得所有表的列表幅聘, 不管是永久的還是臨時的,可以使用類似下面的命令:
SELECT name FROM
(SELECT * FROM sqlite_master UNION ALL
SELECT * FROM sqlite_temp_master)
WHERE type=’table’
ORDER BY name