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的使用
如题。

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