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閱讀 230,106評論 6 542
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,441評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,211評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,736評論 1 317
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,475評論 6 412
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,834評論 1 328
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,829評論 3 446
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 43,009評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,559評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,306評論 3 358
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,516評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,038評論 5 363
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,728評論 3 348
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,132評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,443評論 1 295
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,249評論 3 399
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,484評論 2 379

推薦閱讀更多精彩內容