Android数据库

SQLite及其封装

Posted by candy1126xx on May 26, 2017

SQLite

数据类型

  • NULL: 空值
  • VARCHAR(n):长度不固定且其最大长度为 n 的字串,n不能超过 4000。
  • CHAR(n):长度固定为n的字串,n不能超过 254。
  • INTEGER: 值被标识为整数,依据值的大小可以依次被存储为1,2,3,4,5,6,7,8.
  • REAL: 所有值都是浮动的数值,被存储为8字节的IEEE浮动标记序号.
  • TEXT: 值为文本字符串,使用数据库编码存储(TUTF-8, UTF-16BE or UTF-16-LE).
  • BLOB: 值是BLOB数据块,以输入的数据格式进行存储。如何输入就如何存储,不改 变格式。
  • DATA :包含了 年份、月份、日期。
  • TIME: 包含了 小时、分钟、秒。

Insert语句

INSERT INTO TABLE_NAME [(column1, column2…)] VALUES (value1, value2…); 或

INSERT INTO TABLE_NAME VALUES (value1,value2…);要注意与列序一致

Select语句

SELECT column1, column2… FROM TABLE_NAME;

或获取所有列:SELECT * FROM TABLE_NAME

带WHERE子句:SELECT column1, column2… FROM TABLE_NAME WHERE [condition];

Update语句

UPDATE TABLE_NAME SET column1 = value1, column2 = value2… WHERE [condition];

Delete语句

DELETE FROM TABLE_NAME WHERE [condition];

条件运算

…… WHERE [condition1] AND [condition2] OR [condition3];

对SQLite的封装

SQLiteDatabase

SQLiteConnectionPool

SQLiteDatabaseConfiguration

使用

打开或者创建数据库

// 一般地,path是"/data/data/包名/databases/xxx.db"
SQLiteDatabase.openOrCreateDatabase(String path, SQLiteDatabae.CursorFactory factory)

创建表

创建表没有提供方法。只能编写SQL语句。一般写在SQLiteOpenHelper.onCreate()回调中。

// create table usertable(...)创建一张名为usertable的表
// _id integer primary key autoincrement: 主键为_id,唯一且自增
// sname text,snumber text: 2列数据,列名为sname、snumber,类型都是TEXT
String sql = "create table usertable(_id integer primary key autoincrement,sname text,snumber text)";
db.execSQL(stu_table);

删除表

创建表没有提供方法。只能编写SQL语句。

String sql = "DROP TABLE IF EXISTS " + tableName;
db.execSQL(sql);

插入数据

ContentValues cValue = new ContentValues();
// 表中有几列,就要put几个键值对
cValue.put("...", "...");
cValue.put("...", "...");
db.insert(表名, ContentValues为空时的默认值, cValue);

删除数据

String 条件 = "id=?";
String[] 条件参数 = {String.valueOf(2)};
db.delete(表名, 条件, 条件参数); // 删除id = 2的那行数据

修改数据

ContentValues values = new ContentValues();  
values.put(列名, 值);  
String 条件 = "id=?";  
String[] 条件参数 = {String.valuesOf(1)};  
db.update(表名, values, 条件, 条件参数); // 把id = 1的那行数据的“列名”那个数据改为“值”

查询数据

Cursor c = db.query(表名, [列名], 条件, [条件参数], 结果集按哪个列名分组, 组条件, 升序or降序, 输出几行数据)

Cursor是一个结果集,可以再用它的方法查询特定某个数据。

升级数据库

在SQLite数据库中有1张名为sqlite_master的表,记录了“表名”和“建表语句”,于是可以分析出所有旧版本数据表的所有列名。

// Table类用于封装1张表的所有列名
public Map<String, Table> getOldTables() {
    final String table = "sqlite_master";
    final String[] columns = {"name", "sql"};
    Cursor cursor = mDB.query(table, columns, "type='table'", null, null, null, null);
    HashMap<String, Table> ret = null;
    if (cursor.getCount() > 0) {
        ret = new HashMap<String, Table>(cursor.getCount());
        Table tmp;
        while (cursor.moveToNext()) {
            tmp = new Table(cursor.getString(0), cursor.getString(1));
            ret.put(tmp.Name, tmp);
        }
    }
    cursor.close();
    return ret == null ? Collections.EMPTY_MAP : ret;
}

在SQLiteOpenHelper.onUpgrade()回调中,

Map<String, Table> oldMap = getOldTables();
Iterator<Table> iterator = tableList.iterator();
Table table;
Table oldTable;
String tempTableName
// 迭代所有新表
while (iterator.hasNext()) {
	table = iterator.next();
	// 如果没有叫这个名字的表,说明该表是新建的
	if ((oldTable = oldMap.get(table.Name)) == null) {
	   // 新建表
   		db.execSQL(table.CreateSql);
       continue;
	}
   // 如果有,但是列名都没变,那么也不需要迁移数据
   oldMap.remove(table.Name);
   if (oldTable.equalsColumns(table)) {
   		continue;
   }
   // 列名变了,要迁移数据了
   tempTableName = table.Name + TEMP_SUFFIX;
   // 创建临时表,并把旧表数据复制到临时表
   createTmpTableAndCopy(table.Name, tempTableName);
   // 删除旧表
   deleteTable(table.Name);
   // 创建新表
   createNewTable(table.Name);
   // 把临时表数据复制到新表
   copyToNewTable(tempTableName, table.Name);
}
// 删除剩余的旧表
deleteObsoleteTables(oldMap.values());

其中createTmpTableAndCopy()的SQL语句是:

"CREATE TABLE IF NOT EXISTS " + tempTableName + " AS SELECT * FROM " + oldTableName;

copyToNewTable()的SQL语句是:

// columns是新表所有列名的字符串数组
"INSERT INTO " + newTableName + "(" + columns + ") SELECT " + columns + " FROM " + tempTableName;