SQLite數(shù)據(jù)庫(kù)的使用方法

SQLite是一種嵌入式的數(shù)據(jù)庫(kù)引擎驯妄,最后是以文件的形式保存數(shù)據(jù)的能耻,專門適用于資源有限的設(shè)備上進(jìn)行適量的數(shù)據(jù)存儲(chǔ)帆竹,而Android全面支持標(biāo)準(zhǔn)的SQLite數(shù)據(jù)庫(kù)绕娘。
  所有創(chuàng)建的SQLite數(shù)據(jù)庫(kù),僅限于當(dāng)前應(yīng)用訪問(wèn)栽连,如果其他應(yīng)用需要訪問(wèn)险领,則必須提供的ContentProvider的支持侨舆,并且SQLite數(shù)據(jù)庫(kù)會(huì)隨著Android應(yīng)用的卸載而被刪除。
  從本質(zhì)上來(lái)看绢陌,SQLite的操作方式只是一種更為便捷的文件操作挨下,當(dāng)應(yīng)用程序創(chuàng)建或打開(kāi)一個(gè)SQLite數(shù)據(jù)庫(kù)時(shí),其實(shí)只是打開(kāi)一個(gè)文件準(zhǔn)備讀寫脐湾。
  因?yàn)镾QLite僅適用于資源有限的小型設(shè)備臭笆,所以本身就不應(yīng)該把大量數(shù)據(jù)存儲(chǔ)在設(shè)備的SQLite數(shù)據(jù)庫(kù)里,SQLite只適合存儲(chǔ)一些小型的數(shù)據(jù)秤掌。
  為了使SQLite和其他數(shù)據(jù)庫(kù)間的兼容性最大化愁铺,SQLite支持對(duì)列上類型進(jìn)行“類型近似”,列的類型近似指的是存儲(chǔ)在列上的數(shù)據(jù)進(jìn)行推薦類型存儲(chǔ)闻鉴。所以雖然SQLite內(nèi)部只支持null(空)茵乱、integer(整型)、real(浮點(diǎn)數(shù))椒拗、text(文本)和blob(二進(jìn)制)這五種數(shù)據(jù)類型似将,但實(shí)際上SQLite完全可以接受varchar(n)、char(n)蚀苛、decimal(p, s)在验、date等類型數(shù)據(jù),只不過(guò)SQLite會(huì)在運(yùn)算或保存時(shí)將它們轉(zhuǎn)換為上面五種數(shù)據(jù)類型中相應(yīng)的類型堵未。大多數(shù)數(shù)據(jù)庫(kù)的引擎都是使用靜態(tài)的腋舌、強(qiáng)類型的數(shù)據(jù)類型,數(shù)據(jù)的類型是由它的容器決定的渗蟹,這個(gè)容器是指被存放的特定列块饺。而SQLite使用的是動(dòng)態(tài)類型,在SQLite中雌芽,值的數(shù)據(jù)類型跟值本身相關(guān)授艰,而不是與它的容器相關(guān),所以SQLite允許把各種類型的數(shù)據(jù)保存到任何類型字段中世落,開(kāi)發(fā)者可以不用關(guān)心聲明該字段說(shuō)使用的數(shù)據(jù)類型淮腾。但是有一種情況例外,定義為integer primary key的字段只能存儲(chǔ)64位整數(shù)屉佳,當(dāng)向這種字段保存除整數(shù)意外的其他類型的數(shù)據(jù)時(shí)谷朝,SQLite會(huì)產(chǎn)生錯(cuò)誤。

SQLite數(shù)據(jù)庫(kù)文件存放位置

/data/data/<package name>/databases/

SQLite數(shù)據(jù)庫(kù)支持的數(shù)據(jù)類型

SQLite內(nèi)部只支持null(空)武花、integer(整型)圆凰、real(浮點(diǎn)數(shù))、text(文本)和blob(二進(jìn)制)這五種數(shù)據(jù)類型体箕。

SQLiteOpenHelper

SQLiteOpenHelper提供了兩個(gè)構(gòu)造器专钉,用于傳遞當(dāng)前上下文對(duì)象以及SQLite數(shù)據(jù)庫(kù)版本信息挑童,在SQLiteOpenHelper的繼承類的構(gòu)造函數(shù)中會(huì)調(diào)用它,構(gòu)造器的簽名如下:

SQLiteOpenHelper(Context context, String name,
                 SQLiteDatabase.CursorFactory factory, int version)
SQLiteOpenHelper(Context context, String name,
                 SQLiteDatabase.CursorFactroy factory, int version,
                 DatabaseErrorHandler errorHandler)

上面的構(gòu)造函數(shù)中跃须,都是用于創(chuàng)建一個(gè)SQLite數(shù)據(jù)庫(kù)炮沐,context為一個(gè)當(dāng)前應(yīng)用的上下文對(duì)象;name是數(shù)據(jù)庫(kù)名稱回怜;factory是一個(gè)允許子類在查詢時(shí)使用的游標(biāo),一般不用(傳null即可)换薄;version是數(shù)據(jù)庫(kù)版本號(hào)玉雾;errorHandler是一個(gè)接口,傳遞當(dāng)數(shù)據(jù)庫(kù)錯(cuò)誤的時(shí)候轻要,執(zhí)行的補(bǔ)救方法复旬。

在SQLiteOpenHelper中,可以進(jìn)行SQLite數(shù)據(jù)庫(kù)的創(chuàng)建冲泥、維護(hù)驹碍、日志以及獲取可讀寫的數(shù)據(jù)庫(kù)對(duì)象,通過(guò)下面幾個(gè)常用方法得到支持:
  1)String getDatabaseName():獲取數(shù)據(jù)庫(kù)名凡恍。
  2)SQLiteDatabase getReadableDatabase():創(chuàng)建或者打開(kāi)一個(gè)可讀的數(shù)據(jù)庫(kù)對(duì)象志秃。
  3)SQLiteDatabase getWritableDatabase():創(chuàng)建或者打開(kāi)一個(gè)可讀/寫的數(shù)據(jù)庫(kù)對(duì)象。
  4)abstract void onCreate(SQLiteDatabase db):當(dāng)?shù)谝淮握{(diào)用SQLiteOpenHelper的時(shí)候執(zhí)行嚼酝,之后再次調(diào)用將不再執(zhí)行浮还,一般用于完成數(shù)據(jù)庫(kù)初始化的工作。
  5)void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion):當(dāng)數(shù)據(jù)庫(kù)版本號(hào)發(fā)生向上更新時(shí)被執(zhí)行闽巩。
  6)void onDowngrade(SQLiteDatabase db, int oldVersion, int newVersion):當(dāng)數(shù)據(jù)庫(kù)版本號(hào)發(fā)生向下更新時(shí)被執(zhí)行钧舌。

SQLiteDatabase

當(dāng)使用SQLiteOpenHelper的getReadableDatabase()或者getWritableDatabase()方法獲取到SQLiteDatabase對(duì)象,就可以對(duì)這個(gè)數(shù)據(jù)庫(kù)進(jìn)行操作了涎跨。

CRUD

其中C代表添加(Create)洼冻,R代表查詢(Retrieve),U代表更新(Update)隅很,D代表刪除(Delete)撞牢。

1、使用SQL語(yǔ)句執(zhí)行CRUD操作

1)插入數(shù)據(jù)

db.execSQL("insert into book (name, author, pages, price) values(?, ?, ?, ?)",
new String[] { "The Da Vinci Code", "Dan Brown", "454", "16.96" });

2)更新數(shù)據(jù)

db.execSQL("update book set price = ? where name = ?", new String[] { "10.99", "The Da Vinci Code" });

3)刪除數(shù)據(jù)

db.execSQL("delete from book where pages > ?", new String[] { "500" });

4)查找數(shù)據(jù)

db.rawQuery("select * from book", null);

void execSQL():通過(guò)SQL語(yǔ)句執(zhí)行一條非查詢語(yǔ)句外构。
Cursor rawQuery():通過(guò)SQL語(yǔ)句執(zhí)行一條查詢語(yǔ)句普泡。

2、使用SQLiteDatabase所提供的方法實(shí)現(xiàn)CRUD操作

1)插入一條數(shù)據(jù)

long insert(String table, String nullColumnHack, ContentValues values)

table是表名审编;nullColumnHack用于在未指定添加數(shù)據(jù)的情況下給某些可為空的列自動(dòng)賦值null撼班,一般用不到這個(gè)功能,直接傳入null即可垒酬;values是一個(gè) ContentValues對(duì)象砰嘁,它提供了一系列的put()方法重載件炉,用于向ContentValues中添加數(shù)據(jù),只需要將表中的每個(gè)列名以及相應(yīng)的待添加數(shù)據(jù)傳入即可矮湘。
  2)根據(jù)條件斟冕,刪除數(shù)據(jù)。

int delete(String table, String whereCaluse, String[] whereArgs)

table是表名缅阳;whereCaluse和whereArgs用于去約束刪除某一行或某幾行的數(shù)據(jù)磕蛇,不指定的話默認(rèn)就是刪除所有行∈欤  
  3)根據(jù)條件秀撇,更新數(shù)據(jù)。

int updata(String table,ContentValues values,String whereCaluse,String[] whereArgs)

table是表名向族;values是ContentValues對(duì)象要把更新數(shù)據(jù)在這里組裝進(jìn)去呵燕;whereCaluse和whereArgs用于去約束更新某一行或某幾行中的數(shù)據(jù),不指定的話默認(rèn)就是更新所有行件相。
  4)根據(jù)條件再扭,查詢數(shù)據(jù)。

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

table是表名夜矗;columns用于指定去查詢哪幾列泛范,如果不指定則默認(rèn)查詢所有列;selection和selectionArgs用于去約束查詢某一行或某幾行的數(shù)據(jù)侯养,不指定則默認(rèn)是查詢所有行的數(shù)據(jù)敦跌;groupBy用于指定需要去group by的列,不指定則表示不對(duì)查詢結(jié)果進(jìn)行g(shù)roup by操作逛揩;having用于對(duì)group by之后的數(shù)據(jù)進(jìn)行進(jìn)一步的過(guò)濾柠傍,不指定則表示不進(jìn)行過(guò)濾;orderBy用于指定查詢結(jié)果的排序方式辩稽,不指定則表示使用默認(rèn)的排序方式惧笛。

示例演示

1)SQLiteOpenHelper幫助創(chuàng)建和更新數(shù)據(jù)庫(kù)

public class DBOpenHelper extends SQLiteOpenHelper {

    private Context mContext;
    private String createBook;
    private String createCategory;

    public DBOpenHelper(Context context, String name,
                        SQLiteDatabase.CursorFactory factory, int version) {
        super(context, name, factory, version);
        mContext = context;
    }

    /**
     * 創(chuàng)建數(shù)據(jù)庫(kù)
     */
    @Override
    public void onCreate(SQLiteDatabase db) {
        // 創(chuàng)建book表
        createBook = "create table book(" +
                "id integer primary key autoincrement, " +
                "author text, " +
                "price real, " +
                "pages integer, " +
                "name text, " +
                "category_id integer)";
        db.execSQL(createBook);
        // 創(chuàng)建category表
        createCategory = "create table category(" +
                "id integer primary key autoincrement, " +
                "category_name text, " +
                "category_code integer)";
        db.execSQL(createCategory);
        // 提示數(shù)據(jù)庫(kù)創(chuàng)建完畢
        Toast.makeText(mContext, "數(shù)據(jù)庫(kù)創(chuàng)建完畢", Toast.LENGTH_SHORT).show();
    }

    /**
     * 更新數(shù)據(jù)庫(kù)
     */
    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        switch (oldVersion) {
            case 1:
                // 創(chuàng)建category表
                db.execSQL(createCategory);
            case 2:
                // 向book表添加category_id列
                db.execSQL("alter table book add column category_id integer");
                break;
        }
    }
}

2)設(shè)置Activity的布局
activity_main.xml

<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <Button
        android:id="@+id/add_data"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="添加數(shù)據(jù)"/>

    <Button
        android:id="@+id/update_data"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="更新數(shù)據(jù)"/>

    <Button
        android:id="@+id/delete_data"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="刪除數(shù)據(jù)"/>

    <Button
        android:id="@+id/query_data"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="查詢數(shù)據(jù)"/>
</LinearLayout>

3)在Activity中進(jìn)行數(shù)據(jù)庫(kù)的CRUD操作
MainActivity.java

public class MainActivity extends AppCompatActivity {

    private static final String TAG = "MainActivity";

    private DBOpenHelper mDBOpenHelper;
    private SQLiteDatabase mSqLiteDatabase;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // 數(shù)據(jù)庫(kù)BookStore.db,版本2逞泄。
        mDBOpenHelper = new DBOpenHelper(this, "BookStore.db", null, 2);

        /**
         * 插入數(shù)據(jù)
         */
        findViewById(R.id.add_data).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                // 以可寫入的方式獲取數(shù)據(jù)庫(kù)
                mSqLiteDatabase = mDBOpenHelper.getWritableDatabase();
                // 創(chuàng)建ContentValues并寫入數(shù)據(jù)
                ContentValues values = new ContentValues();

                values.put("name", "The Da Vinci Code");
                values.put("author", "Dan Brown");
                values.put("pages", 454);
                values.put("price", 16.96);
                // 插入第一條數(shù)據(jù)
                mSqLiteDatabase.insert("book", null, values);
                // 清空ContentValues
                values.clear();

                values.put("name", "The Lost Symbol");
                values.put("author", "Dan Brown");
                values.put("pages", 510);
                values.put("price", 19.95);
                // 插入第二條數(shù)據(jù)
                mSqLiteDatabase.insert("book", null, values);
                // 清空ContentValues
                values.clear();

                Toast.makeText(MainActivity.this, "已插入數(shù)據(jù)", Toast.LENGTH_SHORT).show();
            }
        });
        /**
         * 更新數(shù)據(jù)
         */
        findViewById(R.id.update_data).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                // 以可寫入的方式獲取數(shù)據(jù)庫(kù)
                mSqLiteDatabase = mDBOpenHelper.getWritableDatabase();
                // 創(chuàng)建ContentValues并寫入數(shù)據(jù)
                ContentValues values = new ContentValues();
                values.put("price", 10.99);
                // 更新數(shù)據(jù)
                mSqLiteDatabase.update("book", values,
                        "name = ?", new String[]{"The Da Vinci Code"});
                Toast.makeText(MainActivity.this, "已更新數(shù)據(jù)", Toast.LENGTH_SHORT).show();
            }
        });
        /**
         * 刪除數(shù)據(jù)
         */
        findViewById(R.id.delete_data).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                // 以可寫入的方式獲取數(shù)據(jù)庫(kù)
                mSqLiteDatabase = mDBOpenHelper.getWritableDatabase();
                mSqLiteDatabase.delete("book", "pages > ?", new String[]{"500"});
                Toast.makeText(MainActivity.this, "已刪除數(shù)據(jù)", Toast.LENGTH_SHORT).show();
            }
        });
        /**
         * 查詢數(shù)據(jù)
         */
        findViewById(R.id.query_data).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                // 以只讀的方式獲取數(shù)據(jù)庫(kù)
                mSqLiteDatabase = mDBOpenHelper.getReadableDatabase();
                // 查詢book表中所有數(shù)據(jù)
                Cursor cursor = mSqLiteDatabase.query("book", null, null, null, null, null, null);
                // 遍歷Cursor對(duì)象患整,取出數(shù)據(jù)。
                while (cursor.moveToNext()) {
                    String name = cursor.getString(cursor.getColumnIndex("name"));
                    String author = cursor.getString(cursor.getColumnIndex("author"));
                    int pages = cursor.getInt(cursor.getColumnIndex("pages"));
                    double price = cursor.getDouble(cursor.getColumnIndex("price"));
                    Log.i(TAG, "name: " + name + ", author: " + author +
                            ", pages: " + pages + ", price: " + price);
                }
                // 記得關(guān)閉資源
                cursor.close();
                Toast.makeText(MainActivity.this, "已查詢數(shù)據(jù)", Toast.LENGTH_SHORT).show();
            }
        });
    }
}

使用事務(wù)

SQLiteDatabase db = dbHelper.getWritableDatabase();
// 開(kāi)啟事務(wù)
db.beginTransaction(); 
try {
    db.delete("Book", null, null);

    ContentValues values = new ContentValues();
    values.put("name", "Game of Thrones");
    values.put("author", "George Martin");
    values.put("pages", 720);
    values.put("price", 20.85);
    db.insert("Book", null, values);

    // 操作成功
    db.setTransactionSuccessful();
} catch (Exception e) {
    e.printStackTrace();
} finally {
    // 關(guān)閉事務(wù)
    db.endTransaction();
}

參考

《第一行代碼--Android》
Android--數(shù)據(jù)持久化之SQLite

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末喷众,一起剝皮案震驚了整個(gè)濱河市各谚,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌到千,老刑警劉巖昌渤,帶你破解...
    沈念sama閱讀 216,591評(píng)論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異憔四,居然都是意外死亡膀息,警方通過(guò)查閱死者的電腦和手機(jī)杠愧,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,448評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門芯肤,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)狡汉,“玉大人浅悉,你說(shuō)我怎么就攤上這事∪吣穑” “怎么了埠对?”我有些...
    開(kāi)封第一講書人閱讀 162,823評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)裁替。 經(jīng)常有香客問(wèn)我鸠窗,道長(zhǎng),這世上最難降的妖魔是什么胯究? 我笑而不...
    開(kāi)封第一講書人閱讀 58,204評(píng)論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮躁绸,結(jié)果婚禮上裕循,老公的妹妹穿的比我還像新娘。我一直安慰自己净刮,他們只是感情好剥哑,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,228評(píng)論 6 388
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著淹父,像睡著了一般株婴。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上暑认,一...
    開(kāi)封第一講書人閱讀 51,190評(píng)論 1 299
  • 那天困介,我揣著相機(jī)與錄音,去河邊找鬼蘸际。 笑死座哩,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的粮彤。 我是一名探鬼主播根穷,決...
    沈念sama閱讀 40,078評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼导坟!你這毒婦竟也來(lái)了屿良?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書人閱讀 38,923評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤惫周,失蹤者是張志新(化名)和其女友劉穎尘惧,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體闯两,經(jīng)...
    沈念sama閱讀 45,334評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡褥伴,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,550評(píng)論 2 333
  • 正文 我和宋清朗相戀三年谅将,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片重慢。...
    茶點(diǎn)故事閱讀 39,727評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡饥臂,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出似踱,到底是詐尸還是另有隱情隅熙,我是刑警寧澤,帶...
    沈念sama閱讀 35,428評(píng)論 5 343
  • 正文 年R本政府宣布核芽,位于F島的核電站囚戚,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏轧简。R本人自食惡果不足惜驰坊,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,022評(píng)論 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望哮独。 院中可真熱鬧拳芙,春花似錦、人聲如沸皮璧。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 31,672評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)悴务。三九已至睹限,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間讯檐,已是汗流浹背羡疗。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 32,826評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留别洪,地道東北人顺囊。 一個(gè)月前我還...
    沈念sama閱讀 47,734評(píng)論 2 368
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像蕉拢,于是被迫代替她去往敵國(guó)和親特碳。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,619評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容