Android | SQLite的使用(附步驟提煉)

核心:SQLiteOpenHelper幫助類(是一個(gè)抽象類)

借助這個(gè)類就可以非常簡單地對(duì)數(shù)據(jù)庫進(jìn)行創(chuàng)建和升級(jí)民泵;

創(chuàng)建數(shù)據(jù)庫

  • SQLiteOpenHelper是抽象類,需創(chuàng)建自己的類繼承;

  • 其中有兩個(gè)抽象方法静檬,
    onCreate()onUpgrade()帘营,
    需重寫,實(shí)現(xiàn)創(chuàng)建升級(jí)數(shù)據(jù)庫的邏輯翩活。

  • 還有兩個(gè)重要的實(shí)例方法:
    getReadableDatabase()getWritableDatabase()判没。
    都可創(chuàng)建打開現(xiàn)有數(shù)據(jù)庫(數(shù)據(jù)庫已經(jīng)存在則直接打開,沒有則創(chuàng)建)隅茎,
    并返回可對(duì)數(shù)據(jù)庫進(jìn)行讀寫操作的對(duì)象澄峰。

    其不同:當(dāng)數(shù)據(jù)庫不可寫入時(shí)(如磁盤空間已滿)
    前者返回的對(duì)象以getReadableDatabase()打開數(shù)據(jù)庫辟犀,getWritableDatabase()將出現(xiàn)異常俏竞。

  • SQLiteOpenHelper有兩個(gè)構(gòu)造方法可供重寫,
    一般使用參數(shù)少一點(diǎn)的那個(gè)構(gòu)造方法堂竟,
    其接收四個(gè)參數(shù):
    Context魂毁,
    數(shù)據(jù)庫名,創(chuàng)建數(shù)據(jù)庫時(shí)使用的就是這里指定的名稱出嘹;
    允許查詢數(shù)據(jù)時(shí)返回一個(gè)自定義的Cursor(一般傳入null)席楚,
    當(dāng)前數(shù)據(jù)庫版本號(hào)(用于升級(jí)操作)。

構(gòu)建SQLiteOpenHelper實(shí)例后税稼,
再調(diào)用他的getReadableDatabase()/getWritableDatabase()方法就能創(chuàng)建數(shù)據(jù)庫
(數(shù)據(jù)庫文件會(huì)存放在/data/data/<package name>/databases/目錄下)烦秩。
此時(shí)重寫的onCreate()方法被執(zhí)行(通常處理創(chuàng)建表的邏輯)。@善汀V混簟!H偶 E浊蕖!

示例代碼

創(chuàng)建名為BookStore.db的數(shù)據(jù)庫曙旭,并新建一張Book表盗舰。
新建MyDatabaseHelper類繼承自SQLiteOpenHelper

public class MyDatabaseHelper extends SQLiteOpenHelper {
    //將見表語句定義成字符串常量
    public  static final String CREATE_BOOK = "create table Book ("
            + "id integer primary key autoincrement, "
            + "author text, "
            + "price real, "
            + "pages integer, "
            + "name text)" ;
    private Context mContext;

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

    @Override
    public void onCreate(SQLiteDatabase db) {
        //在數(shù)據(jù)庫創(chuàng)建完成時(shí)創(chuàng)建Book表
        db.execSQL(CREATE_BOOK);
        Toast.makeText(mContext, "Create succeeded", Toast.LENGTH_SHORT).show();

    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {

    }
}

注意autoincrement表示id是自增長的;

使用MyDatabaseHelper創(chuàng)建數(shù)據(jù)庫

public class MainActivity extends AppCompatActivity {
    private MyDatabaseHelper dbhelper;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        //構(gòu)建SQLiteOpenHelper實(shí)例
        dbhelper = new MyDatabaseHelper(this, "BookStore.db", null, 1);

        Button createDatabase = (Button) findViewById(R.id.create_database);
        createDatabase.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //調(diào)用SQLiteOpenHelper實(shí)例的getReadableDatabase()/getWritableDatabase()方法
              //就能創(chuàng)建數(shù)據(jù)庫了
              //此時(shí)重寫的onCreate()方法被執(zhí)行
              //如以上所寫桂躏,則創(chuàng)建了Book表
                dbhelper.getWritableDatabase();
            }
        });
    }
}

升級(jí)(更新)數(shù)據(jù)庫

基于以上代碼钻趋,
再添加一張Category表用于記錄圖書分類,
在繼承自SQLiteOpenHelperMyDatabaseHelper類中添加代碼:
(添加的地方以感嘆號(hào)標(biāo)記沼头,一共四處)

public class MyDatabaseHelper extends SQLiteOpenHelper {
    //將見表語句定義成字符串常量
    public  static final String CREATE_BOOK = "create table Book ("
            + "id integer primary key autoincrement, "
            + "author text, "
            + "price real, "
            + "pages integer, "
            + "name text)" ;
    //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 1.
    public static final String CREATE_CATEGORY = "create table Category ("
            + "id integer primary key autoincrement, "
            + "category_name text, "
            + "category_code integer)";**

    private Context mContext;

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

    @Override
    public void onCreate(SQLiteDatabase db) {
        //在數(shù)據(jù)庫創(chuàng)建完成時(shí)創(chuàng)建Book表
        db.execSQL(CREATE_BOOK);

        //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 2.
        db.execSQL(CREATE_CATEGORY);
        Toast.makeText(mContext, "Create succeeded", Toast.LENGTH_SHORT).show();

    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {    
        //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 3.
        db.execSQL("drop table if exists Book");
        db.execSQL("drop table if exists Category");
        onCreate(db); //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 4.

    }
}

再次調(diào)用getWritableDatabase();時(shí)爷绘,
onCreate()不會(huì)再執(zhí)行了书劝,
因?yàn)閿?shù)據(jù)庫只能創(chuàng)建一次,剛剛已經(jīng)創(chuàng)建過了土至;

所以這里只能在onUpgrade()中购对,
執(zhí)行Drop將原來的表刪掉,
再重新調(diào)用onCreate()方法陶因,
這樣一開始的表新加的表都會(huì)被創(chuàng)建骡苞;

調(diào)用onUpgrade()

構(gòu)造SQLiteOpenHelper實(shí)例的時(shí)候,
第四個(gè)參數(shù)(version)傳入大于舊版本的數(shù)字楷扬,
即可讓onUpgrade()執(zhí)行解幽,進(jìn)而更新數(shù)據(jù)庫:

public class MainActivity extends AppCompatActivity {
    private MyDatabaseHelper dbhelper;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
        dbhelper = new MyDatabaseHelper(this, "BookStore.db", null, 2);
        //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
        Button createDatabase = (Button) findViewById(R.id.create_database);
        createDatabase.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                dbhelper.getWritableDatabase();
            }
        });
    }
}

CRUD核心:
getReadableDatabase()getWritableDatabase()返回的SQLiteDatabase對(duì)象;
在Android中即使不去編寫SQL語句烘苹,
提供了一系列輔助性方法躲株,
也能輕松完成所有CRUD操作。

SQLiteOpenHelper的兩個(gè)實(shí)例方法getReadableDatabase()/getWritableDatabase()
會(huì)返回SQLiteDatabase對(duì)象镣衡,
借助這個(gè)對(duì)象就可對(duì)數(shù)據(jù)進(jìn)行CRUD操作霜定。

添加數(shù)據(jù)

首先調(diào)用ContentValues實(shí)例的各種重載的put(表的某個(gè)屬性,值)方法廊鸥,
ContentValues實(shí)例自身中添加數(shù)據(jù)望浩;

接著調(diào)用insert()即可將數(shù)據(jù)加到對(duì)應(yīng)的表中惰说;
它接收三個(gè)參數(shù):

  1. 表名磨德,指定向哪張表添加數(shù)據(jù);
  2. 用于在未指定添加數(shù)據(jù)的情況下吆视,
    給某些可為空的列自動(dòng)復(fù)賦值NULL典挑,
    一般用不到這個(gè)功能,
    直接傳入NULL即可揩环;
  3. ContentValues實(shí)例搔弄;
public class MainActivity extends AppCompatActivity {
    private MyDatabaseHelper dbhelper;

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

        dbhelper = new MyDatabaseHelper(this, "BookStore.db", null, 2);
        Button createDatabase = ...

        Button addData = (Button) findViewById(R.id.add_data);
        addData.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                SQLiteDatabase db = dbhelper.getWritableDatabase();
               
                ContentValues values = new ContentValues();

                //開始組裝第一條數(shù)據(jù)
                values.put("name", "The Da Vinci Code");
                values.put("author", "Dan Brown");
                values.put("pages",454);
                values.put("price", 16.96);
                db.insert("Book",null,values);//插入第一條數(shù)據(jù)
                values.clear();//!7峄!5光帧褒墨!

                //開始組裝第二條數(shù)據(jù)
                values.put("name", "The Lost Symbol");
                values.put("author", "Dan Brown");
                values.put("pages",510);
                values.put("price", 19.95);
                db.insert("Book",null,values);//插入第二條數(shù)據(jù)
            }
        });
        ...

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

  1. 首先調(diào)用ContentValues實(shí)例的各種重載的put(表的某個(gè)屬性,值)方法擎宝,
  2. 接著調(diào)用update()實(shí)現(xiàn)更新——
    第三郁妈、四個(gè)參數(shù)用于約束更新某一行或某幾行數(shù)據(jù),
    默認(rèn)更新所有行绍申;
    第三個(gè)參數(shù)對(duì)應(yīng)SQL的where語句噩咪,顾彰?占位符
    通過第四個(gè)參數(shù)提供的字符串?dāng)?shù)組指定相應(yīng)內(nèi)容胃碾;
    第一參數(shù)表名涨享,第二參數(shù)ContentValues實(shí)例;
 Button updateData = (Button) findViewById(R.id.update_data);
        updateData.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                SQLiteDatabase db = dbhelper.getWritableDatabase();
                ContentValues values = new ContentValues();
                values.put("price", 10.99);
                db.update("Book",values, "name = ?", new String[]{"The Da Vinci Code"});
            }
        });

上述代碼表達(dá)的意圖將name為The Da Vinci Code的這本書的價(jià)格改成10.99仆百;

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

  • 直接用SQLiteDatabase實(shí)例調(diào)用delete()厕隧;
    其第一參,表明俄周;
    二三參吁讨,同update()的三四參;
 Button button = (Button) findViewById(R.id.delete_data);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                SQLiteDatabase db = dbhelper.getWritableDatabase();
                db.delete("Book", "pages > ?", new String[]{"500"});
            }
        });

查詢數(shù)據(jù)

  • 通過query()進(jìn)行查詢峦朗;
    其重載方法多建丧,參數(shù)復(fù)雜,
    我們看參數(shù)最少(7個(gè)參數(shù))的一個(gè)波势;
    參數(shù)對(duì)應(yīng)內(nèi)容可參考下表:
    (其三四參茶鹃,同update()的三四參;)

  • query()參數(shù)多艰亮,
    但是多數(shù)情況不必要全部參數(shù)都用闭翩,
    指定少數(shù)幾個(gè)參數(shù)即可完成查詢
    (如只傳入第一個(gè)參數(shù)表名,
    后面全為null迄埃,則查詢表中的所有數(shù)據(jù))疗韵;

    調(diào)用query()后會(huì)返回一個(gè)Cursor(n.光標(biāo))對(duì)象
    查詢到的所有數(shù)據(jù)都將從這個(gè)對(duì)象中取出侄非;

示例代碼:

Button queryButton = (Button) findViewById(R.id.query_data);
        queryButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                SQLiteDatabase db = dbhelper.getWritableDatabase();
                //查詢Book表中所有數(shù)據(jù)
                Cursor cursor = db.query("Book", null,null,null,null,null,null);
                if (cursor.moveToFirst()){
                    do {
                        //遍歷Cursor對(duì)象蕉汪,取出數(shù)據(jù)并打印
                        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.d("MainActivity", "book name is " + name);
                        Log.d("MainActivity", "book author is " + author);
                        Log.d("MainActivity", "book pages is " + pages);
                        Log.d("MainActivity", "book price is " + price);
                    }while (cursor.moveToNext());
                }
                cursor.close();
            }
        });

Cursor實(shí)例每次指向返回?cái)?shù)據(jù)表的一行,
通過moveToFirst()moveToNext()等方法來調(diào)節(jié)其指向的位置逞怨;
令其指向某一行者疤,或者一行一行遍歷返回的數(shù)據(jù)表,
對(duì)返回的數(shù)據(jù)進(jìn)行處理即可叠赦。

項(xiàng)目碼云地址

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末驹马,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖吐葵,帶你破解...
    沈念sama閱讀 217,907評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異泳姐,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)暂吉,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,987評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門胖秒,熙熙樓的掌柜王于貴愁眉苦臉地迎上來缎患,“玉大人,你說我怎么就攤上這事阎肝〖酚妫” “怎么了?”我有些...
    開封第一講書人閱讀 164,298評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵盗痒,是天一觀的道長蚂蕴。 經(jīng)常有香客問我,道長俯邓,這世上最難降的妖魔是什么骡楼? 我笑而不...
    開封第一講書人閱讀 58,586評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮稽鞭,結(jié)果婚禮上鸟整,老公的妹妹穿的比我還像新娘。我一直安慰自己朦蕴,他們只是感情好篮条,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,633評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著吩抓,像睡著了一般涉茧。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上疹娶,一...
    開封第一講書人閱讀 51,488評(píng)論 1 302
  • 那天伴栓,我揣著相機(jī)與錄音,去河邊找鬼雨饺。 笑死钳垮,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的额港。 我是一名探鬼主播饺窿,決...
    沈念sama閱讀 40,275評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼移斩!你這毒婦竟也來了肚医?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,176評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤叹哭,失蹤者是張志新(化名)和其女友劉穎忍宋,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體风罩,經(jīng)...
    沈念sama閱讀 45,619評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,819評(píng)論 3 336
  • 正文 我和宋清朗相戀三年舵稠,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了超升。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片入宦。...
    茶點(diǎn)故事閱讀 39,932評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖室琢,靈堂內(nèi)的尸體忽然破棺而出乾闰,到底是詐尸還是另有隱情,我是刑警寧澤盈滴,帶...
    沈念sama閱讀 35,655評(píng)論 5 346
  • 正文 年R本政府宣布涯肩,位于F島的核電站,受9級(jí)特大地震影響巢钓,放射性物質(zhì)發(fā)生泄漏病苗。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,265評(píng)論 3 329
  • 文/蒙蒙 一症汹、第九天 我趴在偏房一處隱蔽的房頂上張望硫朦。 院中可真熱鬧,春花似錦背镇、人聲如沸咬展。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,871評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽破婆。三九已至,卻和暖如春胸囱,著一層夾襖步出監(jiān)牢的瞬間祷舀,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,994評(píng)論 1 269
  • 我被黑心中介騙來泰國打工旺矾, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留蔑鹦,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,095評(píng)論 3 370
  • 正文 我出身青樓箕宙,卻偏偏與公主長得像嚎朽,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子柬帕,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,884評(píng)論 2 354

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