Android中SQLite的基本使用(二)

来源:互联网 发布:中小企业网络搭建 编辑:程序博客网 时间:2024/06/05 18:22

根据前面的学习,相信大家都能明白 Android 中 SQLite 数据库是如何创建的,这里我来讲下 SQLite 在 Android 中的数据操作。

数据库表

在我们的 SQLite 数据库中,数据的存储是以表的形式,所以在创建数据库的时候我们也应该创建一张数据表,学习过 SQL 语句的都知道要创建一张完整的数据表,需要表名和列名,而这些事我们有可能要去修改的,所以为了效率,我们应该把这些设置为常量去使用,前面我们建立了一个 Constant 类,让我们添加些数据进去:

public class Constant {    public static final String DATABASE_NAME = "info.db"; //数据库名称    public static final int DATABASE_VERSION = 1; //数据库版本    public static final String TABLE_NAME = "person"; //表名    public static final String _ID = "_id";    public static final String NAME = "name";    public static final String AGE = "age";}

可以看到,我们又添加了表名和三个字段,这样就方便我们日后修改。

让我们回到 MySQLiteHelper 类:

    public void onCreate(SQLiteDatabase db) {        Log.i("TAG", "-------onCreate--------");        String sql = "create table " + Constant.TABLE_NAME + " (" +                Constant._ID + " Integer primary key, " +                Constant.NAME + " varchar(10)," +                Constant.AGE + " Integer)";        db.execSQL(sql);    }

execSQL(String sql) 是 SQLiteDatabase 类的执行 SQL 语句的方法,大家将刚才生成的 info.db 删除,再次运行,这样就能在创建数据库文件的时候创建一张 PERSON 的表啦。

我们把生成的 info.db 导出到桌面或者你自己的某个硬盘目录下,用可视化数据库工具打开,你就可以看到数据库的信息,自然也能看到我们新创建的那张表。

我用的是 Navicat Premium,大家可以从这里下载。

SQL语句增删改查

在 Android 中我们可以自己写 sql 语句去执行,但如果觉得写 sql 语句容易出错,也可以调用 api 中的方法。在 SQLite 中,查询操作是特别的,insert,update,delete都对数据做了修改,但 select 只返回结果,所以我们需要能接收这个结果,这样就不能使用 execSQL 方法啦。

我们还有两个方法可以执行查询,分别是 rawQuery 和 query,query() 是 api 拼接 sql 语句,我们暂且不提。

rawQuery(String sql, String[] selectionArgs),sql 就是执行的 select 语句,selectionArgs 是查询条件的占位符,如果没有占位符,就传入null即可,最后会返回一个 Cursor 对象,帮我们确定数据的位置。

DBManager 类是我们用来管理数据库的工具类,execSQL() 是我们必须用到的方法,为了防止出错,我们应该在 DBManager 类中写个方法来判断,同样 rawQuery() 也应该判断。

    public static void execSQL(SQLiteDatabase db, String sql) {        if (db != null) {            if (sql != null && !"".equals(sql)) {                db.execSQL(sql);            }        }    }    public static Cursor selectDataBySql(SQLiteDatabase db, String sql, String[] selectionArgs) {        Cursor cursor = null;        if (db != null) {            cursor = db.rawQuery(sql, selectionArgs);        }        return cursor;    }

相信大家都能够看懂,这里就不讲啦。

rawQuery 是返回一个 Cursor 游标,那么我们自然需要把它转换为熟悉的 list 集合,首先我们要有存储数据的实体类,这就是 Java Bean 思想。

public class Person {    private int _id;    private String name;    private int age;    public Person(int _id, String name, int age) {        this._id = _id;        this.name = name;        this.age = age;    }    @Override    public String toString() {        return "Person{" +                "_id=" + _id +                ", name='" + name + '\'' +                ", age=" + age +                '}';    }    public int get_id() {        return _id;    }    public void set_id(int _id) {        this._id = _id;    }    public String getName() {        return name;    }    public void setName(String name) {        this.name = name;    }    public int getAge() {        return age;    }    public void setAge(int age) {        this.age = age;    }}

有了这个 Person 类,我们就可以在 DBManager 中写从 Cursor 中读数据的方法啦。

public static List<Person> cursorTolist(Cursor cursor) {        List<Person> list = new ArrayList<Person>();        while (cursor.moveToNext()) {            //getColumnIndex(String columnName) 根据参数中指定的字段名称获取字段下标            int columnIndex = cursor.getColumnIndex(Constant._ID);            //getInt(int columnIndex)根据参数中指定的字段下标 获取对应int类型的value            int _id = cursor.getInt(columnIndex);            String name = cursor.getString(cursor.getColumnIndex(Constant.NAME));            int age = cursor.getInt(cursor.getColumnIndex(Constant.AGE));            Person person = new Person(_id, name, age);            list.add(person);        }        return list;    }

根据字段名获取字段下标,再得到字段的 value,懂得一点 Cursor 知识的朋友应该都能明白。

 public void click(View view) {        switch (view.getId()) {            case R.id.btn_insert :                SQLiteDatabase db = helper.getWritableDatabase();                for (int i = 1; i <= 30; i++) {                    String sql1 = " insert into " + Constant.TABLE_NAME + " values(" + i + ",'张三" + i + "'," + i + ") ";                    DbManager.execSQL(db, sql1);                }                db.close();                break;            case R.id.btn_update :                db = helper.getWritableDatabase();                String updatesql=" update "+ Constant.TABLE_NAME + " set " + Constant.NAME +                       "='xiao' where " + Constant._ID + "=1";                DbManager.execSQL(db,updatesql);                db.close();                break;            case R.id.btn_delete :                db = helper.getWritableDatabase();                String deletesql = " delete from " + Constant.TABLE_NAME + " where " + Constant._ID + "=2";                DbManager.execSQL(db,deletesql);                db.close();                break;            case R.id.btn_query :                db = helper.getWritableDatabase();                String sql = "select * from " + Constant.TABLE_NAME;                Cursor cursor = DbManager.selectDataBySql(db, sql, null);                List<Person> list = DbManager.cursorTolist(cursor);                for (Person p: list) {                    Log.i("TAG", p.toString());                }                db.close();                break;        }    }

因为这个代码只是测试数据,所以就随便添加,只要实现功能即可。

这些代码是很容易理解的,现在打开模拟器点击按钮来看看。

这里写图片描述

我们可以看到表中已经有了30条数据,并且 id = 2的数据已经被删除了,id = 1的数据名字也已经别改成了 xiao,这说明我们的功能已经实现了。这里要注意的是,如果你按了几次 insert,会报错,因为 id 重复了,这并没什么。

因为我们执行的 select 是查询全部信息,所以查询结果也显然成功啦。

API 操作

数据库的增删改查需要正确的 SQL 语句,如果对 SQL 语句不熟练的用提供的 api 也是一样的。

insert

insert(String table, String nullColumnHack, ContentValues values)

table:相信大家都能理解是数据表名。

nullColumnStack:因为在 SQLite 中可以允许列中有 NULL,但不能整列都是NULL,这个值代表强行插入null值的数据列的列名,我们都是给 null 就可以了。

values:代表一行记录的数据。insert 方法插入的一行记录使用ContentValues存放,我们看看它的说明。

private HashMap<String, Object> mValues;

可以知道 ContentValues 是一个键为 String 的 HashMap集合,它提供了多种 put(String key, XXX value) (其中key为数据列的列名)方法用于存入数据,多种 getAsXxx(String key) 方法用于取出数据。

insert 方法返回 long,代表新添记录的行号,该行号是一个内部直,与主键id无关,发生错误返回-1。

update

update(String table, ContentValues values, String whereClause, String[] whereArgs)

table 与 values 和 insert 方法是一样的。

whereClause:表示修改条件,满足该whereClause子句的记录将会被更新。

whereArgs:表示修改条件的占位符,用于为whereArgs子句传递参数。

update 方法返回一个 int,表示修改的数据条数。

delete

delete(String table, String whereClause, String[] whereArgs)

table:代表想删除数据的表名。
whereClause:满足该whereClause子句的记录将会被删除。
whereArgs:用于为whereArgs子句传入参数。

与 update 方法中的格式是一样的。

query

query(boolean distinct, String table, String[] columns, String selection, String[] selectionArgs, String groupBy, String having, String orderBy)

  • distinct:指定是否去除重复记录。
  • table:执行查询数据的表名。
  • columns:要查询出来的列名。
  • selection:查询条件子句。
  • selectionArgs:用于为selection子句中占位符传入参数值,值在数组中的位置与占位符在语句中的位置必须一致,否则就会有异常。
  • groupBy:用于控制分组。
  • having:用于对分组进行过滤。
  • orderBy:用于对记录进行排序。
  • limit:用于进行分页。

最后返回 Cursor 游标。

public void onClick(View view) {        switch(view.getId()) {            case R.id.btn_insertApi :                SQLiteDatabase db = helper.getWritableDatabase();                ContentValues values = new ContentValues();                values.put(Constant._ID, 2); //put(表示插入数据库的字段名称,表示插入该字段的具体值)                values.put(Constant.NAME, "Lily");                values.put(Constant.AGE, 15);                long result = db.insert(Constant.TABLE_NAME, null, values);                if (result > 0) {                    Toast.makeText(this, "插入数据成功", Toast.LENGTH_SHORT).show();                } else {                    Toast.makeText(this, "插入数据失败", Toast.LENGTH_SHORT).show();                }                db.close();                break;            case R.id.btn_updateApi :                db = helper.getWritableDatabase();                ContentValues cv = new ContentValues();                cv.put(Constant.NAME, "cc");//put(表示需要修改的字段名称, 修改后的字段值)//                int count = db.update(Constant.TABLE_NAME, cv, Constant._ID + "=3", null);                int count = db.update(Constant.TABLE_NAME, cv, Constant._ID + "=?", new String[]{"3"});                if (count > 0) {                    Toast.makeText(this, "修改数据成功", Toast.LENGTH_SHORT).show();                } else {                    Toast.makeText(this, "修改数据失败", Toast.LENGTH_SHORT).show();                }                db.close();                break;            case R.id.btn_deleteApi :                db = helper.getWritableDatabase();                int count2 = db.delete(Constant.TABLE_NAME, Constant._ID + "=?", new String[]{"1"});                if (count2 > 0) {                    Toast.makeText(this, "删除数据成功", Toast.LENGTH_SHORT).show();                } else {                    Toast.makeText(this, "删除数据失败", Toast.LENGTH_SHORT).show();                }                db.close();                break;            case R.id.btn_queryApi :                db = helper.getWritableDatabase();                Cursor cursor = db.query(Constant.TABLE_NAME, null, Constant._ID + ">?",                new String[]{"10"}, null, null, Constant._ID + " asc");                List<Person> list = DbManager.cursorTolist(cursor);                for (Person p : list) {                    Log.i("TAG", p.toString());                }                db.close();                break;        }    }

这可以看到,在写查询条件的时候有两种写法:

db.update(Constant.TABLE_NAME, cv, Constant._ID + "=3", null);db.update(Constant.TABLE_NAME, cv, Constant._ID + "=?", new String[]{"3"});

这两种是完全一样的。

并没有出现强退,我们看看数据表的变化。

可以看到我们已经删除了 id = 1 的数据,并且以前 id = 2 被删除的数据也插入了新的,id = 3 的数据也被修改了,再看看查询。

id > 10 的数据都被输出了,说明我们 api 的功能也都实现啦。

结束语:本文仅用来学习记录,参考查阅。

3 0
原创粉丝点击