Android数据存储之SQLite数据库存储,数据库的CRUD操作(增、查、改、删)(创建BookStore.db数据库,创建Book表,并了解adb shell来查看数据库和表的创建情况)

GitHub项目地址:

https://github.com/Skymqq/DatabaseSave.git

SQLite是一款轻量级的关系型数据库,它的运算速度非常快,占用资源也很少,通常只需要几百KB的内存就足够了,因而特别适合在移动设备上使用。SQLite不仅支持标准的SQL语法,还遵循了数据库的ACID事务,所以只要你以前使用过其他的关系型数据库,就可以很快的上手SQLite。而SQLite又比一般的数据库要简单的多,它甚至不用设置用户名和密码就可以使用。Android正是把这个功能极为强大的数据库嵌入到了系统中,使用本地持久化的功能有了一次质的飞跃。

文件存储和SharedPreferences存储毕竟只适用于保存一些简单的数据和键值对,当需要存储大量复杂的关系型数据的时候,你就会发现这两种存储方式很难应付。比如我们手机的短信程序中可能会有很多个会话,每个会话中又包含了很多条信息内容,并且大部分会话还可能各自对应了电话薄中的某个联系人。很难想象如何用文件或者SharedPreferences来存储这些数据量大、结构性复杂的数据吧?但是使用数据库就可以做得到。那么我们就赶快来看一看,Android中的SQLite数据库到底是如何使用的。

创建数据库

Android为了让我们能够更加方便地管理数据库,专门提供了一个SQLiteOpenHelper帮助类,借助这个类就可以非常简单地对数据库进行创建和升级。既然有好东西可以直接使用,那么我们当然要尝试一下了,下面我就对SQLiteOpenHelper的基本用法进行介绍。

首先你要知道SQLiteOpenHelper是一个抽象类,这意味着如果我们想要使用它的话,就需要创建一个自己的帮助类去继承它。SQLiteOpenHelper中有两个抽象方法,分别是onCreate()和onUpgrade(),我们必须在自己的帮助类里面重写这两个方法,然后分别在这两个方法中去实现创建、升级数据库的逻辑。

SQLiteOpenHelper中还有两个非常重要的实例方法:getReadableDatabase()和getWritableDatabase()。这两个方法都可以创建或打开一个现有的数据库(如果数据库已存在则直接打开,否则创建一个新的数据库),并返回一个可对数据库进行读写操作的对象。不同的是,当数据库不可写入的时候(如磁盘空间已满),getReadableDatabase()方法返回的对象将以只读的方式去打开数据库,而getWritableDatabase()方法则将出现异常。

SQLiteOpenHelper中有两个构造方法可供重写,一般使用参数少一点的那个构造方法即可。这个构造方法中接收4个参数:

第一个参数是Context,这个没什么好说的,必须要有它才能对数据库进行操作。

第二个参数是数据库名,创建数据库时使用的就是这里指定的名称。

第三个参数允许我们在查询数据的时候返回一个自定义的Cursor,一般都是传入null。

第四个参数表示当前数据库的版本号,可用于对数据库进行升级操作。

构建出SQLiteOpenHelper的实例之后,再调用它的getReadableDatabase()或getWritableDatabase()方法就能够创建数据库了,数据库文件会存放在/data/data/<package name>/databases/目录下。此时,重写的onCreate()方法也会得到执行,所以通常会在这里去处理一些创建表的逻辑。

接下来我们通过新建一个DatabaseSave项目来具体的了解SQLiteOpenHelper的使用吧。

这里我们希望创建一个名为BookStore.db的数据库,然后在这个数据库中新建一张Book表,表中有id(主键)、作者、价格、页数和书名等列。创建数据库表当然还是需要用建表语句的,这里也是要考验一下你的SQL基本功了,Book表的创建语句如下所示:

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

integer:整型

text:文本类型

real:浮点型

blob:二进制类型

primary key:主键

autoincrement:自增

 

SQLiteOpenHelper.java代码:

package com.example.administrator.databasesave;

import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.widget.Toast;

public class MyDatabaseHelper extends SQLiteOpenHelper {
    private Context context;

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

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


    @Override
    public void onCreate(SQLiteDatabase db) {
        db.execSQL(CREATE_BOOK);
        Toast.makeText(context, "create table successfully", Toast.LENGTH_SHORT).show();
    }

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

可以看到,我们把建表语句定义成了一个字符常量,然后在onCreate()方法中又调用了SQLiteDatabase的execSQL()方法去执行这条建表语句,并弹出一条Toast提示表示创建成功,这样就可以保证在数据库创建完成的同时还能成功创建Book表。

activity_main.xml代码:

<?xml version="1.0" encoding="utf-8"?>
<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/btn_create"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Create Database"
        android:textAllCaps="false"
        android:textSize="18sp"
        android:textStyle="bold" />
</LinearLayout>

MainActivity.java代码:

package com.example.administrator.databasesave;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;

public class MainActivity extends AppCompatActivity implements View.OnClickListener {
    private Button btn_create;
    private MyDatabaseHelper helper;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initData();
        initView();//初始化UI控件
    }

    private void initData() {
        helper=new MyDatabaseHelper(MainActivity.this,"BookStore.db",null,1);
    }

    private void initView() {
        btn_create=(Button)findViewById(R.id.btn_create);
        btn_create.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()){
            case R.id.btn_create:
                helper.getWritableDatabase();//以可写的方式,创建或打开数据库
                break;
        }
    }
}

效果图:

点击Create Database按钮之后弹出Toast提示,说明此时BookStore.db数据库和Book表应该已经创建成功了,因为当你再次点击Create Database按钮时,不会再有Toast弹出。可是我们怎么才能证明它们确实是被创建成功了呢?如果还是使用Device File Explorer到data/data/com.example.administrator.databasesave/databases/路径下看,如下所示:

生成了3个文件

1.BookStore.db:生成的BookStore数据库文件

2.BookStore.db-shm :共享内存

3.BookStore.db-wal:write-ahead log,是保存的一个日志文件

此时我们通过数据库管理工具打开BookStore.db是看不到任何东西的,连表都看不到,我试了下。

所以这里我在这里介绍另外一种查看方式,通过adb shell来对数据库和表的创建情况进行检查。

 

adb是AndroidSDK中自带的一个调试工具,使用这个工具可以直接对连接在电脑上的手机或模拟器进行调试操作。它存放在sdk的platform-tools目录下,如果想要在命令行中使用这个工具,就需要先把它的路径配置到环境变量里。这里我就暂不演示了,网上教程挺多也挺详细的。

配置好了环境变量之后,就可以使用adb工具了,打开命令行界面。

步骤1:Windows+R  输入 cmd 进入DOS命令行界面。

步骤2:输入 adb shell  回车

步骤3:进入自己的项目路径,如下图所示:

cd  /data/data/com.example.administrtor.databasesave/databases/是我的项目路径

如果你也出现Permission denied,那么你需要输入一下su root命令来获取root权限,然后就可以再操作一次了,如下所示:

步骤3:输入cd  /data/data/com.example.administrtor.databasesave/databases/

步骤4:输入ls   回车之后我们会看到   BookStore.db  BookStore.db-shm  BookStore.db-wal  这3个文件就像我们在Device File Explorer中看到的一样。

步骤5:输入sqlite3 BookStore.db

步骤6:输入 .table(注意前面有个点)

可以看到,此时数据库中有两张表,android_metadata表示每个数据库中都会自动生成的,不用管它,而另外一张Book表就是我们刚刚点击Create Database按钮之后,通过MyDatabaseHelper所创建的。

步骤7:输入.schema(注意前面有个点)

通过.shcema命令,我们可以看到创建表的sql语句,其中第二行的sql语句就是我们创建Book表的语句。


升级数据库:

使用重写的onUpgrade()方法来对数据库进行升级,它在整个数据库的管理工作当中起着非常重要的作用。

目前DatabaseSave项目中已经有一张Book表用于存放书的各种详细数据,如果我们想再添加一张Category表用于记录图书的分类,该怎么做呢?

比如Category表中有id(主键)、分类名和分类代码这几个列,那么建表语句如下:

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

MyDatabaseHelper.java代码:

package com.example.administrator.databasesave;

import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.widget.Toast;

public class MyDatabaseHelper extends SQLiteOpenHelper {
    private Context context;

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

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

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


    @Override
    public void onCreate(SQLiteDatabase db) {
        db.execSQL(CREATE_BOOK);//执行sql语句创建Book表
        db.execSQL(CREATE_CATEGORY);//执行sql语句创建Category表
        Toast.makeText(context, "create table successfully", Toast.LENGTH_SHORT).show();
    }

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

MainActivity.java代码:

package com.example.administrator.databasesave;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;

public class MainActivity extends AppCompatActivity implements View.OnClickListener {
    private Button btn_create;
    private MyDatabaseHelper helper;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initData();
        initView();//初始化UI控件
    }

    private void initData() {
        helper=new MyDatabaseHelper(MainActivity.this,"BookStore.db",null,2);
    }

    private void initView() {
        btn_create=(Button)findViewById(R.id.btn_create);
        btn_create.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()){
            case R.id.btn_create:
                helper.getWritableDatabase();//以可写的方式,创建或打开数据库
                break;
        }
    }
}

注意:这里在MainActivity.java中只将数据库的版本号改为2就行了。

运行效果:

 

为了验证一下Category表是不是已经创建成功了,我们在adb shell中打开BookStore.db数据库,然后键入.table命令和.schema命令,如下所示:

 

步骤1:adb shell

步骤2:cd  项目路径

步骤3:su root(如果出现Permission denied再输入su root命令)

步骤4:cd 项目路径

步骤5:sqlite3 BookStore.db

步骤6:.table

步骤7:.schema


C(Create)添加数据:

现在你已经掌握了创建和升级数据库的方法,接下来就该学习一下如何对表中的数据进行操作了。其实我们可以对数据进行的操作无非4中,即CRUD。

CRUD:

C(Create)添加

R(Retrieve)查询

U(Update)更新

D(Delete)删除

每一种操作又各自对应了一种SQL命令,如果你比较熟悉SQL语言的话,一定会知道

添加数据时使用insert

查询数据时使用select

更新数据时使用update

删除数据时使用delete

但是开发者的水平总是参差不齐的,未必每一个人都能非常熟悉地使用SQL语言,因此Android也提供了一系列的辅助性方法,使得Android中即使不去编写SQL语句,也能轻松完成所有的CRUD操作。

前面我已经知道,调用SQLiteOpenHelper的getReadableDatabase()和getWritableDatabase()方法是可以用于创建和升级数据库的,不仅如此,这两个方法还都会返回一个SQLiteDatabase对象,借助这个对象就可以对数据进行CRUD操作了。

那么下面我们首先学习一下如何向数据库的表中添加数据吧。SQLiteDatabase中提供了一个insert()方法,这个方法就是专门用于添加数据的。它接收3个参数,第一个参数是表名,我们希望向哪张表里添加数据,这里就传入该表的名字。第二个参数用于在未指定添加数据的情况下给某些为空的列自动赋值NULL,一般我们用不到这个功能,直接传入null即可。第三个参数是一个ContentValues对象,它提供了一系列的put()方法重载,用于向ContentValues中添加数据,只需要将表中的每个列名以及相应的待添加数据传入即可。

activity_main.xml代码:

<?xml version="1.0" encoding="utf-8"?>
<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/btn_create"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Create Database"
        android:textAllCaps="false"
        android:textSize="18sp"
        android:textStyle="bold" />

    <Button
        android:id="@+id/btn_add"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Add Data"
        android:textAllCaps="false"
        android:textSize="18sp"
        android:textStyle="bold" />
</LinearLayout>

MainActivity.java代码:

package com.example.administrator.databasesave;

import android.content.ContentValues;
import android.database.sqlite.SQLiteDatabase;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity implements View.OnClickListener {
    private Button btn_create, btn_add;
    private MyDatabaseHelper helper;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initData();
        initView();//初始化UI控件
    }

    private void initData() {
        helper = new MyDatabaseHelper(MainActivity.this, "BookStore.db", null, 2);
    }

    private void initView() {
        btn_create = (Button) findViewById(R.id.btn_create);
        btn_add = (Button) findViewById(R.id.btn_add);

        btn_create.setOnClickListener(this);
        btn_add.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.btn_create:
                helper.getWritableDatabase();//以可写的方式,创建或打开数据库
                break;
            case R.id.btn_add:
                addData();//添加数据
                Toast.makeText(this, "Add Data successfully", Toast.LENGTH_SHORT).show();
                break;
        }
    }

    private void addData() {
        SQLiteDatabase db = helper.getWritableDatabase();
        ContentValues cv = new ContentValues();
        //开始组装第一条数据
        cv.put("name", "The Da Vinci Code");
        cv.put("author", "Dan Brown");
        cv.put("pages", 454);
        cv.put("price", 16.96);
        db.insert("Book", null, cv);
        cv.clear();

        //开始组装第二条数据
        cv.put("name", "The Lost Symbol");
        cv.put("author", "Dan Brown");
        cv.put("pages", 510);
        cv.put("price", 19.95);
        db.insert("Book", null, cv);
    }
}

点击Add Data按钮之后,Toast提示数据已经添加成功,效果图:

为了证实数据已经成功添加,我们还是继续使用adb shell来看一下BookStore.db数据库中的Book表中的数据:

由此可见,我们向ContentValues容器中添加的两组数据都成功地添加到了Book表中。


U(Update)更新数据

学习完了如何向表中添加数据,接下来我们看看怎样才能修改表中已有的数据。SQLiteDatabase中提供了一个非常好用的updata()方法,用于对数据进行更新,这个方法接收4个参数,第一个参数和insert()方法一样,也是表名,在这里指定更新哪一张表 里的数据。第二个参数是ContentValues对象,要把更新数据在这里组装进去。第三、第四个参数用于约束更新某一行或某几行中的数据,不指定的话默认就是更新所有行。

activity_main.xml代码:

<?xml version="1.0" encoding="utf-8"?>
<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/btn_create"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Create Database"
        android:textAllCaps="false"
        android:textSize="18sp"
        android:textStyle="bold" />

    <Button
        android:id="@+id/btn_add"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Add Data"
        android:textAllCaps="false"
        android:textSize="18sp"
        android:textStyle="bold" />

    <Button
        android:id="@+id/btn_update"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Update Data"
        android:textAllCaps="false"
        android:textSize="18sp"
        android:textStyle="bold" />
</LinearLayout>

MainActivity.java代码:

package com.example.administrator.databasesave;

import android.content.ContentValues;
import android.database.sqlite.SQLiteDatabase;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity implements View.OnClickListener {
    private Button btn_create, btn_add, btn_update;
    private MyDatabaseHelper helper;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initData();
        initView();//初始化UI控件
    }

    private void initData() {
        helper = new MyDatabaseHelper(MainActivity.this, "BookStore.db", null, 2);
    }

    private void initView() {
        btn_create = (Button) findViewById(R.id.btn_create);
        btn_add = (Button) findViewById(R.id.btn_add);
        btn_update = (Button) findViewById(R.id.btn_update);

        btn_create.setOnClickListener(this);
        btn_add.setOnClickListener(this);
        btn_update.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.btn_create:
                helper.getWritableDatabase();//以可写的方式,创建或打开数据库
                break;
            case R.id.btn_add:
                addData();//添加数据
                Toast.makeText(this, "Add Data successfully", Toast.LENGTH_SHORT).show();
                break;
            case R.id.btn_update:
                updateData();//更新数据
                Toast.makeText(this, "Update Data successfully", Toast.LENGTH_SHORT).show();
                break;
        }
    }


    private void addData() {
        SQLiteDatabase db = helper.getWritableDatabase();
        ContentValues cv = new ContentValues();
        //开始组装第一条数据
        cv.put("name", "The Da Vinci Code");
        cv.put("author", "Dan Brown");
        cv.put("pages", 454);
        cv.put("price", 16.96);
        db.insert("Book", null, cv);
        cv.clear();

        //开始组装第二条数据
        cv.put("name", "The Lost Symbol");
        cv.put("author", "Dan Brown");
        cv.put("pages", 510);
        cv.put("price", 19.95);
        db.insert("Book", null, cv);
    }

    private void updateData() {
        SQLiteDatabase db = helper.getWritableDatabase();
        ContentValues cv = new ContentValues();
        cv.put("price", 10.99);
        db.update("Book", cv, "name=?", new String[]{"The Da Vinci Code"});
    }
}

点击Update Data按钮之后,Toast提示数据已经更新成功,如下所示:

为了证实数据已经成功更新,我们还是继续使用adb shell来看一下BookStore.db数据库中的Book表中的数据:

之前的数据:

更新之后的数据:

可以看到,我们将名字为The Da Vinci Code的这本书的价格从16.96改成10.99。


D(Delete)删除数据

前面我们学习了一下添加数据和更新数据,代码不多,理解起来也很容易,删除数据也很简单,SQLiteDatabase中提供了一个delete()方法,专门用于删除数据,这个方法接收了3个参数,第一个参数仍然是表名,用于删除那张表中的数据,第二、第三个参数又是用于约束删除某一行或某几行的数据,不指定的话默认就是删除所有行。

activity_main.xml代码:

<?xml version="1.0" encoding="utf-8"?>
<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/btn_create"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Create Database"
        android:textAllCaps="false"
        android:textSize="18sp"
        android:textStyle="bold" />

    <Button
        android:id="@+id/btn_add"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Add Data"
        android:textAllCaps="false"
        android:textSize="18sp"
        android:textStyle="bold" />

    <Button
        android:id="@+id/btn_update"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Update Data"
        android:textAllCaps="false"
        android:textSize="18sp"
        android:textStyle="bold" />

    <Button
        android:id="@+id/btn_delete"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Delete Data"
        android:textAllCaps="false"
        android:textSize="18sp"
        android:textStyle="bold" />
</LinearLayout>

MainActivity.java代码:

package com.example.administrator.databasesave;

import android.content.ContentValues;
import android.database.sqlite.SQLiteDatabase;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity implements View.OnClickListener {
    private Button btn_create, btn_add, btn_update, btn_delete;
    private MyDatabaseHelper helper;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initData();
        initView();//初始化UI控件
    }

    private void initData() {
        helper = new MyDatabaseHelper(MainActivity.this, "BookStore.db", null, 2);
    }

    private void initView() {
        btn_create = (Button) findViewById(R.id.btn_create);
        btn_add = (Button) findViewById(R.id.btn_add);
        btn_update = (Button) findViewById(R.id.btn_update);
        btn_delete = (Button) findViewById(R.id.btn_delete);

        btn_create.setOnClickListener(this);
        btn_add.setOnClickListener(this);
        btn_update.setOnClickListener(this);
        btn_delete.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.btn_create:
                helper.getWritableDatabase();//以可写的方式,创建或打开数据库
                break;
            case R.id.btn_add:
                addData();//添加数据
                Toast.makeText(this, "Add Data successfully", Toast.LENGTH_SHORT).show();
                break;
            case R.id.btn_update:
                updateData();//更新数据
                Toast.makeText(this, "Update Data successfully", Toast.LENGTH_SHORT).show();
                break;
            case R.id.btn_delete:
                deleteData();//删除数据
                Toast.makeText(this, "Delete Data successfully", Toast.LENGTH_SHORT).show();
                break;
        }
    }


    private void addData() {
        SQLiteDatabase db = helper.getWritableDatabase();
        ContentValues cv = new ContentValues();
        //开始组装第一条数据
        cv.put("name", "The Da Vinci Code");
        cv.put("author", "Dan Brown");
        cv.put("pages", 454);
        cv.put("price", 16.96);
        db.insert("Book", null, cv);
        cv.clear();

        //开始组装第二条数据
        cv.put("name", "The Lost Symbol");
        cv.put("author", "Dan Brown");
        cv.put("pages", 510);
        cv.put("price", 19.95);
        db.insert("Book", null, cv);
    }

    private void updateData() {
        SQLiteDatabase db = helper.getWritableDatabase();
        ContentValues cv = new ContentValues();
        cv.put("price", 10.99);
        db.update("Book", cv, "name=?", new String[]{"The Da Vinci Code"});
    }

    private void deleteData() {
        SQLiteDatabase db = helper.getWritableDatabase();
        db.delete("Book", "pages>?", new String[]{"500"});//删除Book表中pages>500的这一行数据。
    }

}

点击Delete Data按钮之后,Toast提示数据已经删除成功,如下所示:

为了证实数据已经成功删除,我们还是继续使用adb shell来看一下BookStore.db数据库中的Book表中的数据:

之前的数据:

删除之后的数据:

前后对比之后,我们发现Book表中pages>500的哪一行数据被成功地删除了。


R(Retrieve)查询数据

终于到了最后一种操作了,掌握了查询数据方法之后,你就将数据库的CRUD操作全部学完了。不过千万不要因此而放松,因为查询数据是CRUD中最复杂的一种操作。

我们都知道SQL的全称是Structured Query Language,翻译成中文就是结构化查询语言。它的大部分功能都体现在“查”这个字上的,而“增删改”只是其中的一小部分功能。由于SQL查询涉及的内容实在是太多了,因此在这里我不准备对它展开来讲解,而是只会介绍Android上的查询功能。如果你对SQL语言非常感兴趣,可以专门找一本SQL的书进行学习。

相信你已经猜到了,SQLIteDatabase中还提供了一个query()方法用于对数据进行查询。这个方法的参数非常复杂,最短的一个方法重载也需要传入7个参数。那么我们就先来看一下这7个参数的各自含义吧:

1.第一个参数:表名(表示我们希望从哪张表中查询数据)

2.第二个参数:用于指定去查询哪几列,如果不指定则默认查询所有列

3.第三个参数和第四个参数:用于约束查询某一行或某几行的数据,不指定则默认查询所有行的数据

4.第五个参数:用于指定需要取group by的列,不指定则表示不对查询结果进行group by操作。

5.第六个参数:用于对group by之后的数据进行进一步的过滤,不指定则表示不进行过滤

6.第七个参数:用于指定查询结果的排序方式,不指定则表示使用默认的排序方式。

 

虽然query()方法的参数非常多,但是不要对它产生畏惧,因为我们不必为每条查询语句都指定所有的参数,多数情况下只需要传入少数几个参数就可以完成查询操作了。调用query()方法后会返回一Cursor对象,查询到的所有数据都将从这个对象中取出。

activity_main.xml代码:

<?xml version="1.0" encoding="utf-8"?>
<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/btn_create"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Create Database"
        android:textAllCaps="false"
        android:textSize="18sp"
        android:textStyle="bold" />

    <Button
        android:id="@+id/btn_add"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Add Data"
        android:textAllCaps="false"
        android:textSize="18sp"
        android:textStyle="bold" />

    <Button
        android:id="@+id/btn_update"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Update Data"
        android:textAllCaps="false"
        android:textSize="18sp"
        android:textStyle="bold" />

    <Button
        android:id="@+id/btn_delete"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Delete Data"
        android:textAllCaps="false"
        android:textSize="18sp"
        android:textStyle="bold" />

    <Button
        android:id="@+id/btn_query"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Query Data"
        android:textAllCaps="false"
        android:textSize="18sp"
        android:textStyle="bold" />
</LinearLayout>

MainActivity.java代码:

package com.example.administrator.databasesave;

import android.content.ContentValues;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity implements View.OnClickListener {
    private Button btn_create, btn_add, btn_update, btn_delete, btn_query;
    private MyDatabaseHelper helper;
    public static final String TAG = "MainActivity";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initData();
        initView();//初始化UI控件
    }

    private void initData() {
        helper = new MyDatabaseHelper(MainActivity.this, "BookStore.db", null, 2);
    }

    private void initView() {
        btn_create = (Button) findViewById(R.id.btn_create);
        btn_add = (Button) findViewById(R.id.btn_add);
        btn_update = (Button) findViewById(R.id.btn_update);
        btn_delete = (Button) findViewById(R.id.btn_delete);
        btn_query = (Button) findViewById(R.id.btn_query);

        btn_create.setOnClickListener(this);
        btn_add.setOnClickListener(this);
        btn_update.setOnClickListener(this);
        btn_delete.setOnClickListener(this);
        btn_query.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.btn_create:
                helper.getWritableDatabase();//以可写的方式,创建或打开数据库
                break;
            case R.id.btn_add:
                addData();//添加数据
                Toast.makeText(this, "Add Data successfully", Toast.LENGTH_SHORT).show();
                break;
            case R.id.btn_update:
                updateData();//更新数据
                Toast.makeText(this, "Update Data successfully", Toast.LENGTH_SHORT).show();
                break;
            case R.id.btn_delete:
                deleteData();//删除数据
                Toast.makeText(this, "Delete Data successfully", Toast.LENGTH_SHORT).show();
                break;
            case R.id.btn_query:
                queryData();//查询数据
                Toast.makeText(this, "Query Data successfully", Toast.LENGTH_SHORT).show();
                break;
        }
    }


    private void addData() {
        SQLiteDatabase db = helper.getWritableDatabase();
        ContentValues cv = new ContentValues();
        //开始组装第一条数据
        cv.put("name", "The Da Vinci Code");
        cv.put("author", "Dan Brown");
        cv.put("pages", 454);
        cv.put("price", 16.96);
        db.insert("Book", null, cv);
        cv.clear();

        //开始组装第二条数据
        cv.put("name", "The Lost Symbol");
        cv.put("author", "Dan Brown");
        cv.put("pages", 510);
        cv.put("price", 19.95);
        db.insert("Book", null, cv);
    }

    private void updateData() {
        SQLiteDatabase db = helper.getWritableDatabase();
        ContentValues cv = new ContentValues();
        cv.put("price", 10.99);
        db.update("Book", cv, "name=?", new String[]{"The Da Vinci Code"});
    }

    private void deleteData() {
        SQLiteDatabase db = helper.getWritableDatabase();
        db.delete("Book", "pages>?", new String[]{"500"});//删除Book表中pages>500的这一行数据。
    }

    private void queryData() {
        SQLiteDatabase db = helper.getWritableDatabase();
        //查询Book表中的所有数据
        Cursor cursor = db.query("Book", null, null, null, null, null, null);
        if (cursor.moveToFirst()) {
            do {
                //遍历Cursor对象,取出数据并打印
                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.e(TAG, "name: " + name);
                Log.e(TAG, "author: " + author);
                Log.e(TAG, "pages: " + pages);
                Log.e(TAG, "price: " + price);
            } while (cursor.moveToNext());
        }
        cursor.close();
    }

}

可以看到,我们首先在查询按钮的点击事件里面用一个queryData()方法将查询的一系列操作给封装了,在这个方法中我们通过调用SQLiteDatabase中的query()方法,然后只填了第一个参数,指定要查询的数据库表,也就是Book表。其余的6个参数,我们都指定为null了,这就表示希望查询这张Book表中的所有数据,虽然这张表中目前只剩下一条数据了。查询完之后就得到了一个Cursor对象,接着我们调用它的moveToFirst()方法将数据的指针移动到第一行的位置,然后进入了一个循环当中,去遍历查询到的每一行数据。在这个循环中可以通过Cursor的getColumnIndex()方法获取到某一列在表中对应的位置索引,然后将这个索引传入到相应的取值方法中,就可以得到从数据库中读取到的数据了。

点击QueryData按钮,Toast提示查询数据成功,效果图如下所示:

日志打印Book表中所查询出来的数据:

adb shell查询BookStore.db数据库、Book表中的数据:

 

 

猜你喜欢

转载自blog.csdn.net/android_studying/article/details/86479021
今日推荐