59. (android开发)SQLite数据库操作

SQLite数据库是一款轻型的数据库,在很多嵌入式产品中使用。它占用的资源非常低,只需要几百K内存就足够了。
对windows/linux/unix等多种操作系统提供支持。目前SQLite3是最新的版本。
android系统集成了SQLite数据库。
我们也可以使用一些工具对SQLite数据库进行可视化的操作。比如: SQLite Expert Personal 是一款免费的工具。

SQLite Expert

可以到 http://www.sqliteexpert.com/ 下载使用。
对于SQLite计划采用一个例子实现对数据库的一些操作,包含:创建数据库和数据表;新增记录;查询记录;修改记录;删除记录。还要能复制数据库以便在其他设备上使用 SQLite Expert 查看。
先构建一个界面。包含6个按钮和一个显示结果的TextView。

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context="com.cofox.functions.SQLite.SQLiteActivity">

    <Button
        android:id="@+id/btnCreateSQLiteDatabaseTable"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="创建SQLite数据库和数据表"
        android:textAllCaps="false" />

    <Button
        android:id="@+id/btnSQLiteInsert"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="新增记录" />

    <Button
        android:id="@+id/btnSQLiteSearch"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="查询记录" />

    <Button
        android:id="@+id/btnSQLiteUpdate"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="修改记录" />

    <Button
        android:id="@+id/btnSQLiteDelete"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="删除记录" />

<ScrollView
    android:layout_width="match_parent"
    android:layout_height="130dp">
    <TextView
        android:id="@+id/ttvwQueryResult"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:text="QueryResult" />
</ScrollView>
    <Button
        android:id="@+id/btnSQLiteDbCopy"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="复制数据库" />
</LinearLayout>

界面

创建SQLite数据库和数据表

首先在onCreate内添加一个数据库文件的路径,让整个APP来使用。

        /**数据库文件的路径*/
        val fileName = filesDir.toString() + "/cofoxTest.db"

之所以使用/***/这种注释方式,是因为这样可让调用fileName的地方,鼠标悬浮的时候可以看到注释内容文字。

        //创建数据库和数据表
        btnCreateSQLiteDatabaseTable.setOnClickListener {

            /**创建数据表的SQL语句*/
            val createTableSQL = "CREATE TABLE [cofoxArticle] (" +
                    "[id] INTEGER PRIMARY KEY AUTOINCREMENT," +
                    "[title] VARCHAR(50)," +
                    "[author] VARCHAR(100)," +
                    "[content] TEXT," +
                    "[date] DATE," +
                    "[status] VARCHAR(20)" +
                    ")"
            val file = File(fileName)
            if (file.exists()){
                //如果文件存在就删除旧文件
                file.delete()
            }
            /**数据库对象*/
            val database = SQLiteDatabase.openOrCreateDatabase(fileName, null)
            //建立数据库数据表
            database.execSQL(createTableSQL)
            database.close()
            Toast.makeText(this, "数据库"+fileName, Toast.LENGTH_LONG).show()
        }

这里创建数据库的时候是强制创建,如果发现有旧的数据库,就先删除旧数据库,然后再创建。表结构是有一个自增的id字段,为Int型。建立成功后会弹出一个提示框。
创建数据库表

写入数据

写入数据采用了2种写入的写法,并且又使用循环做了3次重复写入。这样我们点次按钮,就可以在数据库中增加5条内容略有差别的记录了。最细微的差别就是写入时间date了。

        //写入数据
        btnSQLiteInsert.setOnClickListener {
            val database = SQLiteDatabase.openOrCreateDatabase(fileName, null)

            //第一种方式
            val contentValues = ContentValues()
            contentValues.put("title", "金龙翼")
            contentValues.put("author", "厚土火焰山")
            contentValues.put("content", "go和kotlin的技术公司,企业IT系统移动化解决方案。")
            contentValues.put("date", getNow())
            contentValues.put("status", "edit")
            database.insert("cofoxArticle", null, contentValues)

            //第二种方式
            val insertSQL = "insert into cofoxArticle(title, author, content, date, status) values(?,?,?,?,?)"
            database.execSQL(insertSQL, arrayOf("我的公司","Smith","是专业的软件网络公司,为企业提供IT技术支撑。", getNow(), "publish"))


            //重复添加3条
            for (i in 1..3){
                val insertSQL = "insert into cofoxArticle(title, author, content, date, status) values(?,?,?,?,?)"
                database.execSQL(insertSQL, arrayOf("我的公司","金龙翼","是专业的软件网络公司,为企业提供IT技术支撑。", getNow(), "publish"))
            }

            database.close()

            Toast.makeText(this, "写入数据完成", Toast.LENGTH_LONG).show()
        }

这里的时间用到了一个getNow()函数,是用来获取当前时间的。

/**
 * Cofox 日期函数
 * created at 2017/12/19 0:06
 * 功能描述:返回当前日期,格式:2017-12-19 12:13:55.917
 * file:cofoxFuction.kt
 *
 *
 * 修改历史:
 * 2017/12/19:新建
 *
 */
fun getNow(): String {
    if (android.os.Build.VERSION.SDK_INT >= 24) {
        return SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format(Date())
    } else {
        var tms = Calendar.getInstance()
        return tms.get(Calendar.YEAR).toString() + "-" + tms.get(Calendar.MONTH+1).toString() + "-" + tms.get(Calendar.DAY_OF_MONTH).toString() + " " + tms.get(Calendar.HOUR_OF_DAY).toString() + ":" + tms.get(Calendar.MINUTE).toString() + ":" + tms.get(Calendar.SECOND).toString() + "." + tms.get(Calendar.MILLISECOND).toString()
    }
}

写入完成,这个时候如何查看结果呢?可以使用数据库复制出来的办法。那么先来完成数据库复制的功能吧。

复制数据库

        //数据库复制
        btnSQLiteDbCopy.setOnClickListener {
            copyDb()
        }

copyDb()是把存储在私密文件夹下的数据库保存到内置SD卡的路径。这样就可以很容易的复制到其他地方,不用对手机获取root权限了。

    fun copyDb() {
        val fos = FileOutputStream("/sdcard/cofoxTest.db")
        val fileName = filesDir.toString() + "/cofoxTest.db"
        //获取执行assets/image.png的inputStream对象
        val inputStream = FileInputStream(fileName)
        //定义写入数据时的缓存,每次写入100字节
        val b = byteArrayOf(100)
        var count = 0
        //循环写入文件数据
        while (true) {
            count = inputStream.read(b)
            if (count < 0) {
                break
            }
            fos.write(b, 0, count)
        }
        fos.close()
        inputStream.close()
        Toast.makeText(this, "数据库复制保存成功", Toast.LENGTH_LONG).show()
    }
复制数据库

查看数据库写入内容

查询记录

在手机上获取数据库的内容,并且显示出来。我们把数据显示到TextView控件上。
也来用多种方式实现吧。
先是把title为“我的公司”的记录找出来,但是只显示title和author两个字段。
再用第二种方法,直接写SQL语句的,把所有记录都查出来并显示所有字段。
如果要显示多条记录,就需要用到循环,并且使用 moveToNext() 方法,直到 isAfterLast 为止。

        //查询记录
        btnSQLiteSearch.setOnClickListener {
            val database = SQLiteDatabase.openOrCreateDatabase(fileName, null)
            var queryResult = ""
            //使用 query 方法查询cofoxArticle数据表中的记录
            val cursorl = database.query("cofoxArticle", arrayOf("title", "author"), "title=?", arrayOf("我的公司"), "", "", "")
            try {
                cursorl.moveToFirst()
                queryResult += cursorl.getString(0) + " -> " + cursorl.getString(1) + "\r\n"
            } catch (e: Exception) {
            }

            val querySQL = "select * from cofoxArticle"
            val cursor2 = database.rawQuery(querySQL, null)
            try {
                cursor2.moveToFirst()
                while (!cursor2.isAfterLast){
                    queryResult += cursor2.getString(0) + " -> " +cursor2.getString(1) + " -> " +cursor2.getString(2) + " -> " +cursor2.getString(3) + " -> " +cursor2.getString(4) + " -> " +cursor2.getString(5) + "\r\n"
                    cursor2.moveToNext()
                }
            } catch (e: Exception) {
            }

            ttvwQueryResult.setText(queryResult)
            database.close()

        }
查询结果

查询结果

修改记录

对数据库中现有的记录进行修改是很常用的操作。依然采用参数方式和SQL方式,用2种方法分别实现一次。

        //修改记录
        btnSQLiteUpdate.setOnClickListener {
            val database = SQLiteDatabase.openOrCreateDatabase(fileName, null)

            //第一种方式
            val contentValues = ContentValues()
            contentValues.put("content", "专注为企业提供IT支撑服务的科技型公司。")
            database.update("cofoxArticle", contentValues, "author=?", arrayOf("金龙翼"))
            //第二种那个方式
            val updateSQL = "update cofoxArticle set content='是内部最强大的质量保障' where author=?"
            database.execSQL(updateSQL, arrayOf("Smith"))

            database.close()
            Toast.makeText(this, "修改完成", Toast.LENGTH_LONG).show()
        }

以author为条件,对应修改content内容。


改之前

改之后

删除记录

根据条件可以删除所有满足条件的记录。
这里采用了三种方式。用参数全匹配、SQL语句条件等于、SQL语句条件范围

        //删除数据
        btnSQLiteDelete.setOnClickListener {

            val database = SQLiteDatabase.openOrCreateDatabase(fileName, null)

            database.delete("cofoxArticle", "author=?", arrayOf("金龙翼"))

            val deleteSQL = "delete from cofoxArticle where author=?"
            database.execSQL(deleteSQL, arrayOf("Smith"))

            //id大于2的都删掉
            val deleteSQLThan2 = "delete from cofoxArticle where id>?"
            database.execSQL(deleteSQLThan2, arrayOf("2"))

            database.close()

            Toast.makeText(this, "删除成功", Toast.LENGTH_LONG).show()
        }
删除之后的查询结果

删除之后的数据库复制查看结果

利用以上的内容,可以让APP在初次运行的时候,根据数据库是否存在判断是否需要创建。并且也可以根据用户的选择,对数据库进行初始化。如果有必要,还可以让用户主动的保存自己的数据。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,132评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,802评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,566评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,858评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,867评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,695评论 1 282
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,064评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,705评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,915评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,677评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,796评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,432评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,041评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,992评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,223评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,185评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,535评论 2 343

推荐阅读更多精彩内容