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

Android数据库:SQLite除了.db文件,还多出.db-shm,.db-wal文件 Android数据库:SQLite除了.db文件,还多出.db-shm,.db-wal文件 使用安卓数据库保存文件时,在Android Studio 的 Device File Explorer里数据库文件目录 /data/data/com.urovo.datatopc/databases/DATA.db 发现其目录下不仅有.db文件,还有两个其他文件 .db-shm和.db-wal文件 而且数据库存储文件DATA.db(这是我的数据库名字,你们的可能不一样)保存至本地,通过SQLite Develope 阅读详情

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表中的数据:

 

 

基于ARDUINIO的5路红外循迹小车 基于ARDUINIO的5路红外循迹小车 新手抄袭了很多大神的代码。这里表示感谢。 #define STOP 0 #define FORWARD 1 #define BACKWARD 2 #define STURNLEFT 3 #define STURNRIGHT 4 #define TURNLEFT 5 #define TURNRIGHT 6 #define TURNRIGHT90 7 #define TURNLEFT90 8 int leftA_PIN = A0; int 阅读详情

相关推荐

风力发电机并网模型建立及仿真验证

传统能源日益匮乏,环境污染日趋严重,全球向安全、可靠和环保的可持续能源体系转型迫在眉睫,风电迎来了重要的发展契机。近年来,全球风电迅猛发展,我国已成为世界风电新增装机容量第一的国家。然而,随着风电规模的不断增大,风电场接入对系统影响不容忽视。随着变速恒频风力发电系统优越的性能突出和大容量电力电子技术的成熟,风速随机性引起的功率波动及故障情况下的动态响应,对电能质量,系统电压、频率的稳定性产生的影响需要深入研究。因而,本文结合实际项目,针对变速恒频风力发电系统建模,端口动态特性及对电网电能质量、运行稳定性的影

毕业设计区博客 1640

SQLite数据库的安装和使用

sqlite、数据库

Good_go的博客 9713

(RegionProposal Network)RPN网络结构及详解

RPN(RegionProposal Network)区域生成网络 Faster-RCNN的核心。在这里整理。 1.anchors。 特征可以看做一个尺度51*39的256通道图像,对于该图像的每一个位置,考虑9个可能的候选窗口:三种面积{128,256,512}×{128,256,512}×三种比例{1:1,1:2,2:1}{1:1,1:2,2:1}。这些候选窗口称为anchors...

凹酱的DEEP LEARNING 19万+

.db-shm和.db-wal文件

.db-wal文件 wal意思是write-ahead log,顾名思义就是保存的一个日志,对于提交/回滚目的很有用。 sqlite3.7之后开始提供这个功能,当一个数据库采用WAL模式,所有连接数据的操作都必须使用WAL,然后在在数据库文件夹下生成一个后缀为.db-wal的文件保存操作日志。该日志使SQLite可以在事务失败时回滚更改。 SQLite如何使用它们以及为什么将它们保留这么长时间取决于SQLite的作者。如果数据库未在运行,则删除该文件是完全可以的,实际上,如果存在该文件,它将在重新启动数.

qq_35417527的博客 1万+

Librepilot _64位window10环境下的搭建及一些坑的解决办法

  刚入IT行业的小菜鸟,在window上折腾了四天的librepilot地面控制站的搭建,想着这么辛苦不能白费了,看网上相关资料少得可怜,唯一一个详细教程还是在32位环境下,一大堆坑,所以把自己的经验写下来,供大家一起参考。 参考的原文是:https://www.cnblogs.com/jasonchan1202/p/7809937.html的博客,但是执行下来才发现这个博客对64位系统极其不...

weixin_41426339的博客 2728

知识图谱初步学习(一)——本体+Protege新手学习

文章目录前言(本体详解)1.本体概念2.本体分类3.本体组成4.本体构建方法一、protege简介二、软件使用步骤1.安装2.使用三、问题解决方案汇总 前言(本体详解) 在开始学习知识图谱的过程中,首先就是要了解什么是本体(ontology)。 1.本体概念 本体的概念最初源自于哲学领域,在哲学中的定义为“对世界上客观事物的系统描述,即存在论”。哲学中的本体关心的是客观现实的抽象本质。而在计算机领域,本体是可以在语义的层次上来对知识进行描述,可以看做是某一个领域知识的通用模型。 本体是从客观世界中抽象出来

qq_43654669的博客 3万+

商品展示,SQLite数据库的使用

一,SQLite是轻量级数据库,   1.优点为:占用资源少,运行时间快;   2. 四个要素分别是:原子性,一致性,隔离性和持久性;   3. 支持的五种数据类型:null、integer、real、text、和blob。 二。开发一个商品展示案例,将商品展示,并进行增、删、改、查操作。 具体步骤: 1、创建善品展示案例的布局文件(activity_main); mainAct

qq_37739707的博客 459

【超详细】磁力计数据读取--以IST8310为例

第一章讲了IST8310的特性,I2C通信,最高支持400kHz通信速率,14位或者16位自适应数据输出等特性第二章讲了内部结构第三章讲了电气特性第四章讲了如何联系他们然后数据手册就没了。。。在大疆的开发手册中找到了寄存器的手册,如下:点开I2C配置选项, 下图是配好的:观察IST8310的数据手册,发现其支持最大400kHz的I2C通信速率,也就是快速I2C模式,所以第一行I2C Speed Mode我们选Fast Mode同时不要忘记了在C板中I2C3的两个IO口分别是PA8和PC9(一般来说都是这两个

lmh_12138的博客 1万+

Sqlite .db-shm和.db-wal文件

.db-wal文件 wal意思是write-ahead log,顾名思义就是保存的一个日志,对于提交/回滚目的很有用。 sqlite3.7之后开始提供这个功能,当一个数据库采用WAL模式,所有连接数据的操作都必须使用WAL,然后在在数据库文件夹下生成一个后缀为.db-wal的文件保存操作日志。该日志使SQLite可以在事务失败时回滚更改。 SQLite如何使用它们以及为什么将它们保留这么长时间取决于SQLite的作者。如果数据库未在运行,则删除该文件是完全可以的,实际上,如果存在该文件,它将在重新启动数据.

u010227042的博客 3390

EBS开发_创建AP付款

--以下代码于20181002在Tony环境测试通过 /* BEGIN   --mo_global.init('SQLAP');   apps.fnd_global.apps_initialize(user_id =&gt; 1110, resp_id =&gt; 50597, resp_appl_id =&gt; 20003);   --mo_global.set_policy_context(...

蜗牛先生快跑的博客 4767

【系统架构设计师】十、统一建模语言UML(基本概念|UML2.0|SysML)

UML 2.0 提供了 14 种图,分别是类图、对象图、用例图、序列图、通信图(协作图)、状态图、活动图、构件图(组件图)、部署图、制品图、组合结构图、包图、交互概览图和计时图(定时图)。序列图、通信图、交互概览图和计时图均被称为交互图。 系统建模语言(SysML)是一种通用图形建模语言,用于指定,分析,设计和验证可能包括硬件,软件,信息,人员,程序和设施的复杂系统。特别是,该语言提供了图形表示,其具有用于建模系统需求,行为,结构和参数的语义基础,用于与其他工程分析模型集成。

帅次的博客 2522

Android操作sqlite导入大量数据耗时的解决方法

在Android开发中,需要向sqlite中导入大量数据,按照一般做法是很耗时的,测试了一下,导入一条数据在100ms左右,按照这样的做法,如果导入1万条数据,大约得花17分钟,经过实际测试,确实花了17分钟左右。 解决耗时的办法是利用sqlite的事务来处理。方法如下: 首先获取database对象,然后执行如下方法: db.beginTransaction();      /

路遥知马力 4357

YOLOv8【第一章:基础入门篇·第1节】一文搞定,核心架构深度解析与环境配置!

🏆 本文收录于 《YOLOv8实战:从入门到深度优化》 专栏,该专栏专注于分享我在YOLOv8目标检测模型中的实战经验,涵盖从入门基础到深度优化的全方位解决方案。无论你是计算机视觉的新手,还是具有多年深度学习经验的专家,本专栏都将为你提供高效、可复现的技术方案,助你掌握YOLOv8的核心技术,提升目标检测性能,突破瓶颈,优化模型,并加速项目开发🚀!

**My Coding Family** 2104

SQLite数据库中的.db-shm文件和.db-wal文件

.db-wal文件 wal意思是write-ahead log,顾名思义就是保存的一个日志,对于提交/回滚目的很有用。 sqlite 3.7之后开始提供这个功能,当一个数据库采用WAL模式,所有连接数据的操作都必须使用WAL,然后在数据库文件夹下生成一个后缀为.db-wal的文件保存操作日志。该日志使SQLite可以在事务失败时回滚更改。 SQLite如何使用它们以及为什么将它们保留这么长时间取决于SQLite的作者。如果数据库未在运行,则删除该文件是完全可以的,实际上,如果存在该文件,它将在重新启动数据

JiangDong的博客 1万+

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

廖雪峰Python教程[完整版]

廖雪峰的python教程整理的,已经排好版了,而且还是完整的,适合小白

Android之SQLite数据库使用

SQLite是Android系统集成的一个轻量级的数据库。Android提供了SQLiteDatabase代表一个数据库(底层就是一个数据库文件),一旦应用程序获得了代表指定数据库的SQLiteDatabase对象,接下来可通过SQLiteDatabase对象来管理、操作数据库了。

qq_38056514的博客 7380

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

Android学习:学习使用SQLite数据库(创建数据库,升级数据库,及对数据的CRUD操作)

一、简单的介绍SQLite数据库 1、SQLite 一个非常流行的嵌入式数据库,它支持 SQL 语言,并且只利用很少的内存就有很好的性能。此外它还是开源的,任何人都可以使用它。许多开源项目((Mozilla, PHP, Python)都使用了 SQLite. 2、SQLite 由以下几个组件组成:SQL 编译器、内核、后端以及附件。SQLite 通过利用虚拟机和虚拟数据库引擎(VDBE),使调...

shexianyu的博客 1019

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

Android中数据库的常用操作

制作一个APP模拟电子书店的一部分功能。首先需要创建一个名为BookStore.db的数据库,在数据库中新建一张Book表,表中有id(主键)、作者、价格、页数和书名等列。然后增加一些按钮,分别实现对该数据库进行增加或删除书籍,修改价格,查找书籍信息等操作的功能 在activity_main.xml文件中创建布局,代码如下: [html] view plain 

qq_37724237的博客 607

android sqlite存储数据,使用android studio编写一个简单的使用sqlite存储数据的程序,数据一直保存不了...

android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical">android:id="@+id/create_database"android:layout_width="match_parent"android:layout_height="wrap...

weixin_29858081的博客 189

数据库增删改查(二)

public class MyDatabaseHelper extends SQLiteOpenHelper { //建表Book public static final String CREATE_BOOK="create table Book (" +"id integer primary key autoincrement," +"author text," +"p

相公 502

学习《第一行代码》(十一)

文章目录数据存储1.文件存储2.SharedPreference存储举例(getSharedPreference()):举例(getDefaultSharedPreferences()):3.数据库存储SQLite数据库存储(1)创建数据库(2)升级数据库(3)添加数据 数据存储 1.文件存储 适用于存储简单的文本数据或者二进制数据,若想存复杂的文本数据需自行定义格式规范以便要用到数据时可将数据从...

George_UP的博客 535

Sqlite 的 db-shm和db-wal文件

SQLite数据库操作后会生成和文件,数据库断开后会自动删除,没有断开则会一直存在。如果存在,需要三个文件都移动才可以正常打开访问。db-shm文件:存储临时、缓冲区数据db-wal文件:记录数据库操作,保证数据的一致性。

qq_39527774的博客 800

Android学习历程--Sqlite的使用(商品展示案例)

一、何为Sqlite SQLite是D.Richard Hipp用C语言编写的开源嵌入式数据库引擎,它是一款轻型的数据库,是遵守ACID的关系型数据库管理系统,它的设计目标是嵌入式的,而且由于其占用资源低(占用内存只需几百K)、处理速度快等特点,目前许多嵌入式产品中都使用了它,其中就包括大名鼎鼎的iOS和Android移动操作系统。SQLite能够支持Windows/Linux/Unix等等

不要懒惰又后悔的博客 1450

Android 图书管理实现增删改查

目录结构如下: java代码>> Book.java BookActivity.java BookAdapter.java MainActivity.java MyDatabaseHelper.java UpdateBookActivity.java layout>> activ...

aagwpsh7758的博客 1996

JDBC与MySQL数据库,建立一个帮助类MySQLHelper

一、介绍JDBC和MySQL数据库 1、JDBC Java Data Base Connectivity。 JDBC提供API,这些API可以用于操作数据库,这使Java编写的程序不依赖于具体的数据库。 工作原理:应用程序使用JDBC——连接数据库——发送SQL——处理SQL返回的结果。 2、MySQL: 开源数据库管理系统,目前由Oracle公司维护升级。 是一个网络数据库管理系统,可以使远程的计算机访问它所管理的数据库。 二、第一步:连接数据库 1、需要JDBC-MySQL数据库驱动.

每天八杯水的博客 754

安卓:SqlLite简单案例:实现学生列表的增删改查功能

项目成果展示 代码部分: xml: activity_student_manager.xml 主布局代码文件 <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http:/

fuzhijieabc的博客 3869

Android中SQLlite数据库的增删改查

MyHelper页窜见数据库和方法 public class MyHelper extends SQLiteOpenHelper { public MyHelper(Context context) { super(context, "itcast.db", null, 1); } @Override public void onCreate(SQLiteDatabase db) { //创建数据库 db.execSQL("CREA

红目香薰 1091
上一篇: Android数据存储之SharedPreferencesSave存储(保存数据,读取数据的操作)
下一篇: 使用LitePal操作数据库(CRUD增删改查) 项目已上传GitHub
Android_牧
博客等级 码龄9年 88粉丝 45原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值