SQLite数据库

    |     2015年7月13日   |   数据存储   |     0 条评论   |    1829

数据库是存数据的仓库。通讯录、短信、日历、邮箱都靠本地库。Android 内置的是轻量关系库 SQLite,资源占用很小,不必像 PC 那样先装一套数据库软件。下面从命令行、可视化客户端,再到 SQLiteOpenHelper 增删改查。


一、命令行操作 SQLite

SDK 的 tools 目录有 sqlite3.exe。程序生成的 *.db 一般在 /data/data/包名/databases/*.db。

  1. cmd 里输入 adb shell,进入 shell
  2. cd /data/data/包名/databases/,进入应用库目录
  3. sqlite3 *.db,打开库,用熟悉的 SQL 增删改查
  4. .tables 显示所有表
  5. select * from tablename 查数据

二、可视化操作 SQLite

命令行不熟可以用客户端,例如 sqlitebrowser:从 IDE 文件管理导出 *.db,用软件打开即可。


三、代码操作:SQLiteDatabase 与 OpenHelper

核心类 SQLiteDatabase

拿到 SQLiteDatabase 实例就能执行 SQL。最简写法:

SQLiteDatabase db = openOrCreateDatabase("scxh1502.db", MODE_PRIVATE, null);
db.execSQL("create table student (id INTEGER NOT NULL,name TEXT,PRIMARY KEY(id))");
db.execSQL("insert into student (id,name) values (1001,'张三')");

工程里更常见的是继承 SQLiteOpenHelper,用它管理创建和版本升级,实现 onCreate 和 onUpgrade。

数据库辅助类 SQLiteOpenHelper

public class DataBaseHelper extends SQLiteOpenHelper {
    private final static String DATABASE_NAME = "android1601.db"; //数据库名
    private final static int DATABASE_VERSION = 3; //数据库版本号
    private static String createUserTabelSQL = "create table " + DataColumn.UserTable.TABLE_NAME_USER
            + "("
            + DataColumn.UserTable.COLUMN_NAME_ID + " Integer NOT NULL PRIMARY KEY AUTOINCREMENT,"
            + DataColumn.UserTable.COLUMN_NAME_NAME + " varchar(20),"
            + DataColumn.UserTable.COLUMN_NAME_PASSWORD + " varchar(6) "
            + ")";
    private static String alterUserAddSexSQL = "Alter table " + DataColumn.UserTable.TABLE_NAME_USER
            + " add column " + DataColumn.UserTable.COLUMN_NAME_SEX + " varchar(2)";
    private static String alterUserAddNumberSQL = "Alter table " + DataColumn.UserTable.TABLE_NAME_USER
            + " add column " + DataColumn.UserTable.COLUMN_NAME_NUMBER + " Integer";

    private static String createStudentSQL = "CREATE TABLE "+ DataColumn.StudentTable.TABLE_NAME_SUTDENT
            + "("
            + DataColumn.StudentTable.COLUMN_NAME_ID + " Integer NOT NULL PRIMARY KEY AUTOINCREMENT,"
            + DataColumn.StudentTable.COLUMN_NAME_NAME + " varchar(50), "
            + DataColumn.StudentTable.COLUMN_NAME_AGE + " varchar(3) "
            +")";

    public DataBaseHelper(Context context) {
        super(context, DATABASE_NAME, null, DATABASE_VERSION);
        Logs.e("DataBaseHelper 构造方法");
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
        db.execSQL(createUserTabelSQL);
        Logs.e("onCreate 方法");
    }

    /**
     * 版本号变化时执行。newVersion 必须大于 oldVersion,执行完后 oldVersion = newVersion
     */
    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        Logs.e("onUpgrade 方法 oldVersion: " + oldVersion + " ,newVersion:  " + newVersion);

        switch (oldVersion) {
            case 1: //旧版本 1:加 sex 字段
                db.execSQL(alterUserAddSexSQL);
            case 2: //旧版本 2:加 number,并新建学生表(注意 case 故意不 break,便于连升)
                db.execSQL(alterUserAddNumberSQL);
                db.execSQL(createStudentSQL);
        }
    }
}
public class DataColumn {
    public static class UserTable implements BaseColumns{
        public static final String TABLE_NAME_USER = "user";
        public static final String COLUMN_NAME_NAME = "name";
        public static final String COLUMN_NAME_PASSWORD = "password";
        public static final String COLUMN_NAME_SEX = "sex";
        public static final String COLUMN_NAME_NUMBER = "number";
    }

    public static class StudentTable{
        public static final String TABLE_NAME_SUTDENT = "student";
        public static final String COLUMN_NAME_ID = "_id";
        public static final String COLUMN_NAME_NAME = "name";
        public static final String COLUMN_NAME_AGE = "age";
    }
}

getWritableDatabase() 与 getReadableDatabase() 都能拿到 SQLiteDatabase。后者不是一上来就只读:它先走可写打开,失败(例如磁盘满)再尝试只读。磁盘满时 getWritableDatabase() 会直接出错。


四、创建库与增删改查

1. 创建 / 打开数据库

调用 Helper 的 getReadableDatabase(),首次会回调 onCreate()。

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    DatabaseHelper dbHelper = new DatabaseHelper(this); // Activity 里才用 this
    SQLiteDatabase db = dbHelper.getReadableDatabase();
}

常用 API:

(int) delete(String table, String whereClause, String[] whereArgs)
(long) insert(String table, String nullColumnHack, ContentValues values)
(int) update(String table, ContentValues values, String whereClause, String[] whereArgs)
(void) execSQL(String sql)
(void) close()
(Cursor) query(String table, String[] columns, String selection, String[] selectionArgs,
               String groupBy, String having, String orderBy, String limit)
(Cursor) rawQuery(String sql, String[] selectionArgs) // 预置 SQL,利于防注入

增删改查各有两条路:API 便捷方法,或 execSQL / rawQuery。

2. 添加

insert:

ContentValues cv = new ContentValues();
cv.put("username","Jack Johnson");
cv.put("password","iLovePopMusic");
db.insert("user",null,cv);

execSQL:

String sql = "insert into user(username,password) values ('Jack Johnson','iLovePopMusic')";
db.execSQL(sql);

3. 删除

String whereClause = "username=? and sex=?";
String[] whereArgs = {"Jack Johnson","男"};
db.delete("user",whereClause,whereArgs);
String sql = "delete from user where username='Jack Johnson'";
db.execSQL(sql);

4. 修改

ContentValues cv = new ContentValues();
cv.put("password","iHatePopMusic");
String whereClause = "username=?";
String[] whereArgs = {"Jack Johnson"};
db.update("user",cv,whereClause,whereArgs);
String sql = "update [user] set password = 'iHatePopMusic' where username='Jack Johnson'";
db.execSQL(sql);

5. 查询

query 参数:table 表名,columns 列数组,selection 相当于 where,selectionArgs 条件参数,groupBy / having / orderBy / limit,返回 Cursor(类似 ResultSet)。

Cursor 方法 作用
getCount() 总记录条数
isFirst() / isLast() 是否第一条 / 最后一条
moveToFirst() / moveToLast() 移到首 / 末
move(int offset) 相对移动 offset
moveToNext() / moveToPrevious() 下一条 / 上一条
getColumnIndex(String) 列名 → 列下标

方法一(按条数循环 + move):

Cursor c = db.query("user",null,null,null,null,null,null);
if(c.moveToFirst()){
    for(int i=0;i<c.getCount();i++){
        c.move(i);
        String username = c.getString(c.getColumnIndex("username"));
        String password = c.getString(c.getColumnIndex("password"));
    }
}

方法二(while moveToNext,更常用):

Cursor c = db.query("user",null,null,null,null,null,null);
while(c.moveToNext()){
  int id = c.getInt(c.getColumnIndex("id"));
  String name = c.getString(c.getColumnIndex("name"));
  String number = c.getString(c.getColumnIndex("number"));
  Logs.v("id :"+id + " name :"+name+ " number :"+number);
}

rawQuery 带参数:

Cursor c = db.rawQuery("select * from user where username=?", new String[]{"Jack Johnson"});
if(c.moveToFirst()) {
    String password = c.getString(c.getColumnIndex("password"));
}

一句话总结:Android 用 SQLite;日常走 SQLiteOpenHelper 管创建和升级,增删改用 ContentValues API 或 execSQL,查询用 query / rawQuery 拿 Cursor。

转载请注明来源:SQLite数据库
本文链接地址:https://ai.zhousir.top/?p=882
回复 取消