Quantcast
Channel: CSDN博客移动开发推荐文章
Viewing all articles
Browse latest Browse all 5930

Android中SQLite的基本使用(二)

$
0
0

根据前面的学习,相信大家都能明白 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 的功能也都实现啦。

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

作者:HardWorkingAnt 发表于2017/4/27 15:56:21 原文链接
阅读:72 评论:0 查看评论

Viewing all articles
Browse latest Browse all 5930

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>