Android复习之旅--SQLite

SQLite的知识点实在是太多了,将其一一整理出来可能会耗费太多时间,实在抱歉,或许以后会推出关于SQLite的其它知识点。在此只整理出SQLite的增删改查还有事务处理,并将它们封装到方法中,便于阅读。

SQLite简介
SQLite是一个轻量级数据库,支持SQL语言、事务处理等功能。SQLite没有服务器进程,它通过文件保存数据,该文件是跨平台的,可以放在其他平台中使用。

SQLite支持NULL、INTEGER、REAL(浮点数)、TEXT(字符串)和BLOB(二进制对象,1为true,0为false)5种数据类型。

但实际上SQLite也接收varchar(n)、char(n)、decimal(p,s)等数据类型,只不过在运算或保存时会转换成对应的5种数据类型。因此可以将各种类型的数据保存到任何字段中,而不用关心字段声明的数据类型。这也是SQLite数据库的最大特点。

数据库文件保存的位置

/data/data/<packagename>/databases/xxx.db
数据库在创建的时候默认会创建一张表(metadata.db)来保存系统语言环境

数据库增删改查的SQL语句

  • 增加:insert into 表名(字段名,…) values(值,…)
  • 删除:delete from 表名 where 条件
  • 更新:update 表名 set 字段名=值,… where 条件
  • 查询:select 字段名 from 表名 where 条件

添加约束

在数据库表中,往往会给某些字段添加约束来满足特定的需求

  • 主键:primary key (字段 … primary key)
  • 外键:references (字段 … references data2 (主键))
  • 非空:not null(字段 … not null)
  • 唯一:unique (字段 … unique)
  • 默认值:default (字段 … default 默认值)

SQLiteOpenHelper类的常用方法

这是一个抽象类,该类用于创建数据库和数据库版本更新。需要创建新的类来继承

void onCreate(SQLiteDatabase db);  //创建数据库时调用,子类必须重载此方法
void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion);  //数据库版本更新时调用,子类必须重载此方法
SQLiteDatabase getReadableDatabase();  //创建或打开一个只读的数据库
SQLiteDatabase getWritableDatabase();  //创建或打开一个读写的数据库

SQLiteDatabase类的常用方法

  • 执行带占位符的SQL语句实现增删改查

    /** 带占位符的SQL语句;条件值  */
    void execSQL(String sql, Object[] bindArgs); 
    /** 带占位符的SQL语句;条件值  */
    Curosr rawQuery(String sql, String[] selectionArgs); 
    
  • 或调用API中的方法实现增删改查

    /** 表名;一般为null即可;添加的内容*/
    long insert(String table, String nullColumnHack, ContentValues values); // -1为添加失败
    
    /** 表名;条件;条件值*/
    int delete(String table, String whereClause, String[] whereArgs); // 返回受影响的行数
    
    /** 表名;修改的内容;条件;条件值*/
    int update(String table, ContentValues values, String whereClause, String[] whereArgs); // 返回受影响的行数
    
    /** 表名;返回的列;条件;条件值;group by;having;order by */
    Cursor query(String table, String[] columns, String selection, String[] selectionArgs, String groupBy, String having, String orderBy); //返回结果集
    
    void close();  //关闭数据库
    

两种增删改查的优缺点

  • 自己写sql语句
    • 灵活
    • 资源占用小
    • 可以实现表的级联查询
  • google的现成API
    • 方便
    • 资源开销比较大
    • 有返回值

Cursor接口的常用方法

Cursor是一个游标接口,在数据库操作中返回值,相当于结果集ResultSet

boolean moveToNext(); //移动光标到下一行
boolean moveToFirst(); //移动光标到第一行
boolean moveToPosition(int position); //移动光标到指定位置
int getCount();  //返回Cursor中的行数
int getPosition();  //返回当前Cursor的位置

int getColumnIndex(String columnName);  //返回指定列的索引值,如不存在则返回-1
int getInt(int columnIndex);  //返回指定列的整数值
String getString(int columnIndex);  //返回指定列的字符串

数据库的常用操作

创建一个类继承自SQLiteOpenHelper,复写父类的方法

  public class PersonDBOpenHelper extends SQLiteOpenHelper {

      public PersonDBOpenHelper(Context context) {
          //上下文,数据库名称,游标工厂(默认为null即可),版本号
          super(context, "rixin", null, 1);
      }

      @Override
      public void onCreate(SQLiteDatabase db) {
          // 创建SQLite数据表(数据库第一次创建时调用)
          db.execSQL("create table info (_id integer primary key autoincrement,name varchar(20),age integer)");
      }

      @Override
      public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
          // 数据库的版本升级时调用
          Log.w("info", "数据库升级了");
      }
  }

实例化数据库类

PersonDBOpenHelper helper = new PersonDBOpenHelper(this);

添加记录

/**
 * 添加记录
 * name:要添加记录中的某个字段名
 * age:要添加记录中的某个字段名
 */
public void insertRecord(String name, int age) {
    SQLiteDataBase db = helper.getWritableDatabase(); // 打开一个读写的数据库
    // db.execSQL("insert into info(name,age) values(?,?)", new String[]{name, age});

    ContentValues values = new ContentValues();
    values.put("name", name);
    values.put("age", age);
    long i = db.insert("info", null, values);
    if (i == -1) {
        Toast.makeText(this, "添加记录失败", 0).show();
    } esle {
        Toast.makeText(this, "添加记录成功", 0).show();
    }
    db.close();
}

删除记录

/**
 * 删除记录
 * name:要删除的记录中的某个字段名
 */
public void deleteRecord(String name) {
    SQLiteDatabase db = helper.getReadableDatabase(); // 打开一个只读的数据库
    // db.execSQL("delete from info where name=?", new String[]{name});

    int i = db.delete("info", "name=?", new String[]{name});
    if (i == 0) {
        Toast.makeText(this, "删除记录失败", 0).show();
    } else {
        Toast.makeText(this, "删除记录成功", 0).show();
    }
    db.close();
}

更新记录

/** 
 * 更新记录
 * name:以name字段查询记录
 * age:要修改的字段
 */
public void updateRecord(String name, int age) {
    SQLiteDatabase db = helper.getReadableDatabase(); // 打开一个只读的数据库
    // db.execSQL("update info set age=? where name=?", new String[]{age, name});

    ContentValues values = new ContentValues();
    values.put("age", age);
    int i = db.update("info", values, "name=?", new String[]{name});
    if (i == 0) {
        Toast.makeText(this, "更新记录失败", 0).show();
    } else {
        Toast.makeText(this, "更新记录成功", 0).show();
    }
    db.close();
}

查询记录

/**
 * 查询记录
 * name:以name字段值查询记录
 */
public void queryRecord(String name) {
    SQLiteDatabase db = helper.getReadableDatabase(); // 打开一个只读的数据库
    //得到数据库查询的结果集的游标(指针)
   
    // Cursor cursor = db.rawQuery("select * from info", null); //查询全部记录
    // Cursor cursor = db.rawQuery("select age from info where name=?", new String[]{name});

    // Cursor cursor = db.query("info", null, null, null, null, null, null);
    Cursor cursor = db.query("info", new String[]{"age"}, "name=?", new String[]{name}, null, null, null);
    List<HashMap<String,int>> list = new ArrayList<HashMap<String,int>>();
    while (cursor.moveToNext()) {
        HashMap<String,int> hm = new HashMap<String,int>();
        hm.put("name", cursor.getString(cursor.getColumnIndex("name")));
        hm.put("age", cursor.getInt(cursor.getColumnIndex("age")));
        list.add(hm);
        hm = null;
    }
    cursor.close();
    db.close();
}

事务操作(银行转账等相关需要同步操作数据库的事务)

public void execTransaction(String name1, String name2) {
    SQLiteDatabase db = helper.getWritableDatabase();
    db.beginTransaction();
    try {
        // 转账
        db.execSQL("update info set money=money-100 where name =?", new String[]{name1});
        // 收到转账
        db.execSQL("update info set money=money+100 where name =?", new String[]{name2});
        // 标识事务执行成功,如果没有执行下面的代码,数据会回滚
        db.setTransactionSuccessful();
    } catch(Exception ex) {
        ex.printStackTrace();
        Log.i("rixin", "事务处理失败");
    } finally {
        db.endTransaction(); //关闭事务
        db.close();  //关闭数据库
    }
}

值得注意的是:操作完数据库后要记得关闭数据库,使用完Cursor对象后,也应及时关闭,否则会造成内存泄漏

利用sqlite3工具查看数据库的内容

sqlite3 xxx.db (进去后输入sql语句查询即可)

如果出现中文乱码 需要修改cmd的编码集,默认是gb2312

chcp 65001 (更改cmd窗口的编码的DOS命令,65001是utf-8)

adb shell   (挂载到Linux的空间)
cd data/data/<packagename>/databases  (进入应用的databases目录下)
ls -l  (列出当前目录下的所有文件的详细信息)
sqlite3 xxx.db  
select * from info;  (SQL语句查询,记得加上分号" ; "结束)

如果觉得使用命令来查看数据库表麻烦,也可以google搜索下载可以查看SQLite数据库的软件。导出数据库文件到电脑后即可使用软件来查看数据库里面的信息。

希望以上的内容对你们有所帮助吧

点赞