Android數據庫接口用法簡介

關於Android數據庫的使用,網上和很多書籍上都有相應的介紹,簡單的使用,難度不大,但是作爲一個持久存儲數據的方式,有必要做個總結,以下內容基本參照《第一行代碼》中的有關介紹。

概述

Android爲了讓我們能夠更加方便地管理數據庫,專門提供了一個SQLiteOpenHelper幫助類,藉助這個類就可以非常簡單地對數據庫進行創建和升級。既然有好東西可以直接使用,那我們自然要嘗試一下了,下面我就將對SQLiteOpenHelper的基本用法進行介紹。
首先你要知道SQLiteOpenHelper是一個抽象類,這意味着如果我們想要使用它的話,就需要創建一個自己的幫助類去繼承它。SQLiteOpenHelper中有兩個抽象方法,分別是onCreate()和onUpgrade(),我們必須在自己的幫助類裏面重寫這兩個方法,然後分別在這兩個方法中去實現創建、升級數據庫的邏輯。
SQLiteOpenHelper中還有兩個非常重要的實例方法,getReadableDatabase()和getWritableDatabase()。這兩個方法都可以創建或打開一個現有的數據庫(如果數據庫已存在則直接打開,否則創建一個新的數據庫),並返回一個可對數據庫進行讀寫操作的對象。不同的是,當數據庫不可寫入的時候(如磁盤空間已滿)getReadableDatabase()方法返回的對象將以只讀的方式去打開數據庫,而getWritableDatabase()方法則將出現異常。
SQLiteOpenHelper中有兩個構造方法可供重寫,一般使用參數少一點的那個構造方法即可。這個構造方法中接收四個參數,第一個參數是Context,這個沒什麼好說的,必須要有它才能對數據庫進行操作。第二個參數是數據庫名,創建數據庫時使用的就是這裏指定的名稱。第三個參數允許我們在查詢數據的時候返回一個自定義的Cursor,一般都是傳入null。第四個參數表示當前數據庫的版本號,可用於對數據庫進行升級操作。構建出SQLiteOpenHelper的實例之後,再調用它的getReadableDatabase()或getWritableDatabase()方法就能夠創建數據庫了,數據庫文件會存放在/data/data//databases/目錄下。

代碼

實現Book.java簡單數據類,MySQLHelper.java繼承自SQLiteOpenHelper,MainActivity.java界面操作

  • Layout(只寫一個button的,其他button類似):
 <Button
    android:text="update"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_below="@+id/insert"
    android:layout_alignParentStart="true"
    android:layout_marginTop="17dp"
    android:id="@+id/update"
    android:onClick="updateDataClick" />
  • Book.java
public class Book {
    private String name;
    private float price;
    private int pages;

    public Book(float price, String name, int pages) {
        this.price = price;
        this.name = name;
        this.pages = pages;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public float getPrice() {
        return price;
    }

    public void setPrice(float price) {
        this.price = price;
    }

    public int getPages() {
        return pages;
    }

    public void setPages(int pages) {
        this.pages = pages;
    }

}
  • MySQLHelper.java
public class MySQLHelper extends SQLiteOpenHelper {

    public static final String CREATE_BOOK_TABLE= "create table Book (" +
            "id integer primary key autoincrement," +
            "name text, " +
            "price real," +
            "pages integer," +
            "category_id integer)";

    public static final String CREATE_CATEGORY = "create table Category ("
            + "id integer primary key autoincrement, "
            + "category_name text, "
            + "category_code integer)";

    private static final String TAG = "MySQLHelper";

    private Context mContext;

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


    @Override
    public void onCreate(SQLiteDatabase sqLiteDatabase) {
        Log.d(TAG,"onCreate");
        sqLiteDatabase.execSQL(CREATE_BOOK_TABLE);
        sqLiteDatabase.execSQL(CREATE_CATEGORY);

    }

    //數據庫升級的最佳方式
    @Override
    public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i1) {
        Log.d(TAG,"onUpgrade");
        //刪除數據庫中的表
        //sqLiteDatabase.execSQL("drop table if exists Book");
        Log.d(TAG,"i = "+ i+" i1 = "+i1);
        //機智的沒有使用break
        switch (i){
            case 1:
                sqLiteDatabase.execSQL(CREATE_CATEGORY);
            case 2:
                sqLiteDatabase.execSQL("alter table Book add column category_id integer");
            default:
        }
    }
}
  • MainActivity.java
public class MainActivity extends AppCompatActivity {

    private static final String TAG ="ZYW";
    private Button create;
    private Button insert;
    private Button update;
    private Button delete;
    private Button select;
    private MySQLHelper helper;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.d(TAG,"onCreate");
        setContentView(R.layout.activity_main);
        init();
        //修改version,onUpgrade()方法會被執行到
        helper = new MySQLHelper(this,"DataBase.db",null,2);
    }

    private void init(){
        create = (Button) findViewById(R.id.create);
        insert = (Button) findViewById(R.id.insert);
        update = (Button) findViewById(R.id.update);
        delete = (Button) findViewById(R.id.delete);
        select = (Button) findViewById(R.id.select);
    }

    public void createTableClick(View view) {
        Log.d(TAG,"createTableClick");
        SQLiteDatabase database = helper.getReadableDatabase();
    }

    public void insertDataClick(View view) {
        Log.d(TAG,"insertDataClick");
        SQLiteDatabase database = helper.getReadableDatabase();

        //法1:Android 接口
        /*ContentValues values = new ContentValues();
        Book book = new Book((float) 114.5,"<sangeren>",250);
        Book book1 = new Book((float) 66.5,"<wanglishiwunian>",350);
        Book book2 = new Book((float) 245.5,"<diyihangdaima>",150);
        values.put("name",book.getName());
        values.put("price",book.getPrice());
        values.put("pages",book.getPages());
        database.insert("Book",null,values);
        values.clear();
        values.put("name",book1.getName());
        values.put("price",book1.getPrice());
        values.put("pages",book1.getPages());
        database.insert("Book",null,values);
        values.clear();
        values.put("name",book2.getName());
        values.put("price",book2.getPrice());
        values.put("pages",book2.getPages());
        database.insert("Book",null,values);*/

        //法2:SQLite語句
        //同上,id是自增長的,所以也不需要賦值
        //(name,pages,price): 發現這個順序沒必要和創建表時的順序一致,但是要保證後續賦值的一一對應。
        //('<xuesanfeihu>',555,120.5): 如果使用雙引號的話會報錯,需要使用英文單引號
        // 不加單引號,運行時會報錯:Caused by: android.database.sqlite.SQLiteException: near "<": syntax error (code 1):
        //拓展: 轉義字符
        //String str1 = "\"name\"";//字符串兩邊含有雙引號
        //String str2 = "name \"is\" wgb";//字符串中間含有雙引號
        //String str3 = "\\name";//使用轉義字符還可以使字符串包含其他字符
        //database.execSQL("insert into Book (name,pages,price) values ('<feihu>',432,32.5)");

        //法3:折中方法
        database.execSQL("insert into Book (name,pages,price) values (?,?,?)",new String[]{"<ciqiongle>","421","73.2"});

    }

    public void updateDataClick(View view) {
        Log.d(TAG,"updateDataClick");
        SQLiteDatabase database = helper.getReadableDatabase();
        //法1:Android 接口
        /*ContentValues values = new ContentValues();
        Book book = new Book((float) 333.5,"<HHH>",222);
        values.put("name",book.getName());
        values.put("price",book.getPrice());
        values.put("pages",book.getPages());
        database.insert("Book",null,values);
        database.update("Book",values,"price = ?",new String[]{"245.5"});*/

        //法2:SQLite語句
        //database.execSQL("update Book set price = 321.1 where name = '<ciqiongle>'");

        //法3:折中方法
        database.execSQL("update Book set price = ? where name = ?",new String[]{"123.4","<ciqiongle>"});
    }

    public void deleteDataClick(View view) {
        Log.d(TAG,"deleteDataClick");
        SQLiteDatabase database = helper.getReadableDatabase();
        //法1:Android 接口
        /*database.delete("Book","name = ?",new String[]{"<sangeren>"});*/

        //法2:SQLite語句
        //database.execSQL("delete from Book where name = '<HHH>'");
        //法3:折中方法
        database.execSQL("delete from Book Where name = ?",new String[]{"<feihu>"});
    }

    public void selectDataClick(View view) {
        Log.d(TAG,"selectDataClick");
        SQLiteDatabase database = helper.getReadableDatabase();
        //"id desc": 表示查詢得到的數據,按id降序排列; 升序爲"id asc"
        //"pages between ? and ?": 測試發現查詢得到的數據包含邊界
        //Cursor cursor = database.query("Book", new String[]{"id","name", "price"}, "pages between ? and ?", new String[]{"150","300"}, null, null, "id desc", null);

        //法2:SQLite語句
        Cursor cursor = database.rawQuery("select * from Book where pages between ? and ?", new String[]{"150", "300"});
        if (cursor.moveToFirst()) {
            do {
                // new String[]{"name", "price"}代表最終讀取數據庫中哪幾列的數據,
                // 如果cursor中沒有包含,下面非要去獲取,將報錯Caused by: java.lang.IllegalStateException:
                // Couldn't read row 0, col -1 from CursorWindow.
                // 查詢得到的數據中沒有,你去讀,理當報異常,注意點
                int id = cursor.getInt(cursor.getColumnIndex("id"));
                String name = cursor.getString(cursor.getColumnIndex("name"));
                float price = cursor.getFloat(cursor.getColumnIndex("price"));
                Log.d(TAG,"id = "+id+ " name = "+name+" ; price = "+price);
            }while (cursor.moveToNext());
        }
        //不要忘了
        cursor.close();
    }

    //事務的使用:SQLite數據庫是支持事務的,事務的特性可以保證讓某一系列的操作要麼全部完成,要麼一個都不會完成。
    public void replaceDataClick(View view) {
        Log.d(TAG,"replaceDataClick");
        SQLiteDatabase readableDatabase = helper.getReadableDatabase();
        //事務開始
        readableDatabase.beginTransaction();
        try{
            readableDatabase.delete("Book",null,null);
            if (false) {
                //手動拋出一個異常,讓事務失敗
                throw new NullPointerException();
            }
            readableDatabase.execSQL("insert into Book (name,pages,price) values (?,?,?)",new String[]{"<ciqiongle>","421","73.2"});
            //事務執行成功
            readableDatabase.setTransactionSuccessful();
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            //結束事務
            readableDatabase.endTransaction();
        }
    }
}

關於數據庫常用語句介紹:

1、查找一個表返回其中幾條記錄
select * from table where name= ? limit 0,10;
其中limit 0,10中,0表示從第0條記錄開始,10表示向下10條記錄。

2、根據條件查找一個表,按某字段進行排序
select * from table where name= ? order by id desc或者 asc 或者不填 ;
desc降序排列,asc升序排列
其中id是表中的字段。

3、查詢一個表中,某字段名爲X或者Y的所有數據
select * from LocalModelTable where prodCategory = ? or prodCategory = ?;
其中prodCategory爲字段,名爲X或者Y,返回的是名字爲X、Y下的所有數據。

4、更新一條數據到表中
update LocalSchemeTable set Area = ?,BudgetList = ? ,TimeStamp = ? where SchemeID = ?;

5、插入一條記錄到表中
insert into LocalSchemeTable (Area, BudgetList,Budget) values (?,?,?);

6、給表添加、刪除、修改一列(字段)
alert table table_name add column column_name datatype default 0
舉例: alert table student add column age interger default 0
給student表增加一個字段age ,設置默認值爲0

7、手動添加一個表
create table if not exists LocalProductInfoTable (Num integer primary key autoincrement,marque text);
其中Num爲自增長的編號。text爲文本類型。

8、查看數據庫中是否有某個表
select count(*) as ‘count’ from sqlite_master where type =’table’ and name = ?;
?爲表名。

9、約束
比如有的值不能爲空,有的必須給默認值,有的字段的值必須唯一
建表時可以給特定的字段設置一些約束條件,常見的約束有
not null :規定字段的值不能爲null
unique :規定字段的值必須唯一
default :指定字段的默認值
(建議:儘量給字段設定嚴格的約束,以保證數據的規範性)
舉例
create table student (id integer, name text not null unique, age integer not null default 1) ;
name字段不能爲null,並且唯一
age字段不能爲null,並且默認爲1

10、添加主鍵 自增長
主鍵(Primary Key,簡稱PK)用來唯一地標識某一條記錄,一個表可以有多個主鍵。只要聲明爲primary key,就說明是一個主鍵字段,主鍵字段默認就包含了not null 和 unique 兩個約束。
create table student (id integer primary key, name text, age integer) ;
創建一個student表,設置id爲主鍵。
create table student (id integer primary key autoincrement, name text, age integer) ;
創建一個student表,設置id爲主鍵,並且是自增長類型,需要注意的是,自增長類型主鍵必須!!!是interger類型的。

11、外鍵
外鍵是指本表的某個字段是另外一張表的主鍵。

拓展

Android開發之SQLite詳解
介紹SQLite的內容更詳細,豐富。

Android之存儲篇SQLite數據庫讓你徹底學會SQLite的使用
如題。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章