学习Android之SQLite数据库存储

 SQLite数据库存储

 创建数据库

 Android专门提供了一个SQLiteOpenHelper帮助类,借助这个类可以对数据库进行创建和升级。

 它是一个抽象类,意味着我们要使用它的话就要创建一个类去继承它。有两个抽象方法:onCreate()和onUpgrade()。

 SQLiteOpenHelper中还有两个非常重要的实例方法:getReadableDatabase()和getWritableDatabase()。这两个方法都可以创建或打开一个现有的数据库(如果数据库已存在则直接打开,否则要创建一个新的数据库),并返回一个可对数据库进行读写操作的对象。

 它的构造方法一般重写4个参数的:

  第一个:Context;

  第二个:数据库名;

  第三个:允许我们在查询数据的时候返回一个自定义的Cursor,一般传入null即可;

  第四个:表示当前数据库的版本号,用于对数据库进行升级。

 数据库文件会存放在/data/data/<packagename>/databases/目录下。

 

 创建一个数据库如下:

复制代码
class MyDatabaseHelper(val context: Context, name: String, version: Int) :
    SQLiteOpenHelper(context, name, null, version) {

    private val createBook = "create table Book ( id integer primary key autoincrement," +
            "author text," +
            "price real," +
            "name text)"

    override fun onCreate(p0: SQLiteDatabase) {
        p0.execSQL(createBook)
    }

    override fun onUpgrade(p0: SQLiteDatabase, p1: Int, p2: Int) {
    }
}
复制代码

 

 在MainActivity中进行创建:

        val dbHelper = MyDatabaseHelper(this,"BookStore.db",1)
        dbHelper.writableDatabase

 

 调用了getWritableDatabase()方法。就会检测到当前程序中并没有BookStore.db这个数据库,于是会创建该数据库并调用MyDatabaseHelper中的onCreate()方法,这样Book表也就创建好了。

 

 查看数据库表内容可以借助Database Navigator的插件工具。

 

 升级数据库

 现在数据库中只有一张Book表,如果我们想加一张Category表记录图书的分类。

 以同样的方法写出建表语句,并且在onCreate()中execSQL(createCategory)。

 但这样还不能够创建,因为onCreate()方法只会在第一次创建数据库的时候调用。

 这个时候就要用到onUpgrade()方法。

复制代码
override fun onCreate(p0: SQLiteDatabase) {
p0.execSQL(createBook)
p0.execSQL(createCategory)
}

override fun onUpgrade(p0: SQLiteDatabase, oldVersion: Int, newVersion: Int) {
if (oldVersion <= 1){
p0.execSQL(createCategory)
}
}
复制代码

 

 如果用户数据库的旧版本号小于等于1,就只会创建一张Category表。

 如果用户直接安装第2版,会直接进入onCreate()中,将两张表一起创建。

 

添加数据

 getReadableDatabase()或getWritableDatabase()方法是可以返回一个SQLiteDatabase对象,借助这个对象就可以对数据进行CRUD操作了。

 SQLiteDatabase中提供了一个insert()方法,专门用于添加数据。它接收3个参数;

  第一个:表名;

  第二个:在未指定添加数据的情况下给某些可为空的列自动赋值NULL,一般我们用不到这个功能,直接传入null即可;

  第三个:一个ContentValues对象,它提供了一系列的put()方法重载,用于向ContentValues中添加数据,只需要将表中的每个列名以及相应的待添加数据传入即可。

        val db = dbHelper.writableDatabase
        val values = ContentValues().apply { 
            put("name", "my name is tom")
            put("price", "tom")
            put("price", 19.63)
        }
        db.insert("Book", null, values)

 

更新数据

 update()方法,接收4个参数:

  第一个:表名;

  第二个:ContentValues对象;

  第三、四个:用于约束更新某一行或某几行中的数据,不指定的话默认会更新所有行。

        val db = dbHelper.writableDatabase
        val values = ContentValues()
        values.put("price",15.23)
        db.update("Book",values,"name = ?", arrayOf("my name is tom"))

 第三个参数对应的SQL语句的where部分,第四个参数中arrayOf()方法是Kotlin提供的一种用于便捷创建数组的内置方法。

 删除数据

 delete()方法,专门用于删除数据。这个方法接收3个参数:

  第一个:表名;

  第二、第三:约束删除某一行或某几行的数据,不指定的话默认会删除所有行。

        val db = dbHelper.writableDatabase
        db.delete("Book","price > ?", arrayOf("10"))

 

 表示删除价格在10以上的书籍。

 查询数据

 query()方法,最短的一个方法重载也需要传入7个参数。

  第一个:表名;

  第二个:用于指定去查询哪几列,如果不指定则默认查询所有列。

  第三、第四个:用于约束查询某一行或某几行的数据,不指定则默认查询所有行的数据。

  第五个:用于指定需要去group by的列,不指定则表示不对查询结果进行group by操作。

  第六个:用于对group by之后的数据进行进一步的过滤,不指定则表示不进行过滤。

  第七个:用于指定查询结果的排序方式,不指定则表示使用默认的排序方式。

复制代码
        val db = dbHelper.writableDatabase
        val cursor = db.query("Book", null, null, null, null, null, null)
        if (cursor.moveToFirst()) {
            do {
                val name = cursor.getString(cursor.getColumnIndex("name"))
                val author = cursor.getString(cursor.getColumnIndex("author"))
                val price = cursor.getDouble(cursor.getColumnIndex("price"))
            } while (cursor.moveToNext())
        }
        cursor.close()
复制代码

 

 以上表示查询全部数据。

 

 同时也可以使用SQL语句来进行增删改查。

        //添加
        db.execSQL("insert into Book (author, price, name) values(?,?,?)", arrayOf("newbook","20.23","jack"))
        //更新
        db.execSQL("update Book set price = ? where name = ?", arrayOf("50.2","newbook"))
        //删除
        db.execSQL("delete from book where price > ?", arrayOf("10.00"))
        //查询
        val cursor = db.rawQuery("select * from Book",null)

 

 

 

posted @   PeacefulGemini  阅读(101)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
回顶部
点击右上角即可分享
微信分享提示