【安卓】SQLite数据库存储-创建数据库与增删改查

news2024/9/21 16:47:55

文章目录

      • 创建数据库
      • 更新数据库
      • 增加数据
      • 修改数据
      • 删除数据
      • 查询数据

  安卓专门提供了一个SQLiteOpenHelper帮助类,借助这个类可以非常简单地对数据库进行创建和升级。SQLiteOpenHelper是一个抽象类,使用它需要创建一个自己的帮助类去继承它。SQLiteOpenHelper中有两个抽象方法:onCreate()和onUpgrade()。我们需要在帮助类里重写这两个方法,然后分别在这两个方法中实现创建和升级数据库的逻辑。

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

创建数据库

  SQLiteOpenHelper中有两个构造方法可供重写,一般使用参数少一点的那个构造方法即可。这个构造方法中接收4个参数:第一个参数是Context,这个没什么好说的,必须有它才能对数据库进行操作;第二个参数是数据库名,创建数据库时使用的就是这里指定的名称;第三个参数允许我们在查询数据的时候返回一个自定义的Cursor,一般传入null即可;第四个参数表示当前数据库的版本号,可用于对数据库进行升级操作。构建出SQLiteOpenHelper的实例之后,再调用它的getReadableDatabase()或getWritableDatabase()方法就能够创建数据库了,数据库文件会存放在/data/data//databases/目录下。此时,重写的onCreate()方法也会得到执行,所以通常会在这里处理一些创建表的逻辑。

  新建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) {
        db.execSQL(CREATE_BOOK);
        Toast.makeText(mContext, "Create succeeded", Toast.LENGTH_SHORT).show();
    }

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

  修改activity_main.xml中的代码。

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >
    <Button
        android:id="@+id/createDatabase"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Create Database" />
</LinearLayout>

  最后修改MainActivity中的代码.

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, 1);
        Button createDatabase = (Button) findViewById(R.id.createDatabase);
        createDatabase.setOnClickListener(new View.OnClickListener(){
            @Override
            public void onClick(View v){
                dbHelper.getWritableDatabase();
            }
        });
    }
}

  运行程序之后并不能查看数据库,需要先下载一个插件Database Navigator。

在这里插入图片描述

  安装好插件后需要重启Android studio,重启之后打开Device File Explorer,然后进入/data/data/com.example.databasetest/databases/目录下,可以看到已经存在了一个BookStore.db文件。对着BookStore.db文件右击→Save As,将它从模拟器导出到计算机的任意位置。

  安装好插件之后可以使用快捷键Ctrl + Shift + A(Mac系统是command + shift + A)打开搜索功能,在搜索框中输入“DB Browser”即可找到这个工具。

在这里插入图片描述

  找到保存文件的路径,应用之后就可以在左侧看到数据库的内容了。

在这里插入图片描述

更新数据库

  当数据库BookStore.db已经存在时,MyDatabaseHelper中的onCreate()方法不会再次执行。这里就可以巧妙的利用数据库更新,从而达到新建表的效果。

  修改MyDatabaseHelper.java文件。

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)";
    // 新建表的SQL语句
    public static final String CREATE_CATEGORY = "create table Category ("
            + "id integer primary key autoincrement, "
            + "category_name text, "
            + "category_code inteher)";

    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) {
        db.execSQL(CREATE_BOOK);
        // 在执行onCreate时创建表
        db.execSQL(CREATE_CATEGORY);
        Toast.makeText(mContext, "Create succeeded", 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);
    }
}

  使用db.execSQL将已经存在的表先删除,否则创建已经存在的表会报错。

  SQLiteOpenHelper的构造方法里接收的第四个参数代表的就是版本号,第一次输入的是1,要更新数据库,输入的值就要比上一次大。

  修改MainActivity.java文件,其实就只是修改一下数据库版本号。

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.createDatabase);
        createDatabase.setOnClickListener(new View.OnClickListener(){
            @Override
            public void onClick(View v){
                dbHelper.getWritableDatabase();
            }
        });
    }
}

在这里插入图片描述

增加数据

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

  修改activity_main.xml中的代码。

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >
    <Button
        android:id="@+id/createDatabase"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Create Database" />
    <Button
        android:id="@+id/addData"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Add data" />
</LinearLayout>

  修改MainActivity中的代码。

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.createDatabase);
        createDatabase.setOnClickListener(new View.OnClickListener(){
            @Override
            public void onClick(View v){
                dbHelper.getWritableDatabase();
            }
        });

        Button addData = (Button) findViewById(R.id.addData);
        addData.setOnClickListener(new View.OnClickListener(){
            @Override
            public void onClick(View v){
                SQLiteDatabase db = dbHelper.getWritableDatabase();
                ContentValues values = new ContentValues();
                // 开始组装第一条数据
                values.put("name", "The Da Vinci Code");
                values.put("author", "Dan Brown");
                values.put("pages", 497);
                values.put("price", 17.9);
                db.insert("Book", null, values);
                values.clear();
                // 开始组装第二条数据
                values.put("name", "The Lost Symbol");
                values.put("author", "Dan Brown");
                values.put("pages", 597);
                values.put("price", 27.9);
                db.insert("Book", null, values);
            }
        });
    }
}

  运行程序点击按钮之后,重新保存BookStore.db文件,然后打开DB Browser执行SQL语句select * from Book,就可以看见增加的数据了。

在这里插入图片描述

修改数据

  SQLiteDatabase中提供了一个非常好用的update()方法,用于对数据进行修改。这个方法接收4个参数:第一个参数和insert()方法一样,也是表名,指定更新哪张表里的数据;第二个参数是ContentValues对象,要把更新数据在这里组装进去;第三、第四个参数用于约束更新某一行或某几行中的数据,不指定的话默认会更新所有行。

  修改activity_main.xml中的代码,新加一个按钮用于修改数据。

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >
    <Button
        android:id="@+id/createDatabase"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Create Database" />
    <Button
        android:id="@+id/addData"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Add data" />
    <Button
        android:id="@+id/updateData"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Upadate data" />
</LinearLayout>

  修改MainActivity中的代码,实现修改数据的逻辑。

		Button updateData = (Button) findViewById(R.id.updateData);
        updateData.setOnClickListener(new View.OnClickListener(){
            @Override
            public void onClick(View v){
                SQLiteDatabase db = dbHelper.getWritableDatabase();
                ContentValues values = new ContentValues();
                values.put("price", 19.99);
                db.update("Book", values, "name = ?", new String[]{"The Da Vinci Code"});
            }
        });

  还是和之前操作一样,重新保存一下db文件,然后就可以看到数据更新了。

在这里插入图片描述

删除数据

  SQLiteDatabase中提供了一个delete()方法,专门用于删除数据。这个方法接收3个参数:第一个参数仍然是表名;第二、第三个参数用于约束删除某一行或某几行的数据,不指定的话默认会删除所有行。

  修改activity_main.xml中的代码,新加一个按钮,用于删除数据。

<Button
 android:id="@+id/deleteData"
 android:layout_width="match_parent"
 android:layout_height="wrap_content"
 android:text="Delete Data"
 />

  修改MainActivity中的代码,实现删除功能。

		Button deleteData =(Button) findViewById(R.id.deleteData);
        deleteData.setOnClickListener(new View.OnClickListener(){
            @Override
            public void onClick(View v){
                SQLiteDatabase db = dbHelper.getWritableDatabase();
                db.delete("Book", "pages > ?", new String[] {"500"});
            }
        });

  操作同上,查询之后就可以看见pages大于500的被删除了。

在这里插入图片描述

查询数据

  SQLiteDatabase中提供了一个query()方法用于对数据进行查询。这个方法的参数非常复杂,最短的一个方法重载也需要传入7个参数。第一个参数是表名,表示希望从哪张表中查询数据。第二个参数用于指定去查询哪几列,如果不指定则默认查询所有列。第三、第四个参数用于约束查询某一行或某几行的数据,不指定则默认查询所有行的数据。第五个参数用于指定需要去group by的列,不指定则表示不对查询结果进行group by操作。第六个参数用于对group by之后的数据进行进一步的过滤,不指定则表示不进行过滤。第七个参数用于指定查询结果的排序方式,不指定则表示使用默认的排序方式。

  修改activity_main.xml中的代码,新加一个按钮。

<Button
        android:id="@+id/queryData"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Query Data" />

  修改MainActivity中的代码。

		Button queryData = (Button) findViewById(R.id.queryData);
        queryData.setOnClickListener(new View.OnClickListener(){
            @Override
            public void onClick(View v){
                SQLiteDatabase db = dbHelper.getWritableDatabase();
                // 查询Book表汇中所有的数据
                Cursor cursor = db.query("Book", null, null, null, null, null, null);
                if(cursor.moveToFirst()){
                    do{
                        // 遍历Cursor对象,取出数据并打印
                        String name = cursor.getString(cursor.getColumnIndexOrThrow("name"));
                        String author = cursor.getString(cursor.getColumnIndexOrThrow("author"));
                        int pages = cursor.getInt(cursor.getColumnIndexOrThrow("pages"));
                        double price = cursor.getDouble(cursor.getColumnIndexOrThrow("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();
            }
        });

  打开Logcat就可以看见查询到的内容了。

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1994434.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

巴黎同款,六自由度技术还原赛场决定性瞬间!

现代纪实摄影大师亨利布列松&#xff0c;曾提出了“决定性瞬间”&#xff08;The Decisive Moment&#xff09;理论——拍摄者捕捉到的画面越稍纵即逝&#xff0c;越难以复制&#xff0c;越宝贵。 很多摄影师的经典作品&#xff0c;都来自那决定性的千分之一秒。 ● 布列松摄于…

OpenCV 读取 MP4 视频

在 C 中结合 OpenCV 库来读取 MP4 视频文件是一个常见的任务。以下是一个简单的示例程序&#xff0c;说明了如何使用 OpenCV 的 VideoCapture 类来打开一个 MP4 文件并逐帧显示每一帧。 VideoCapture::VideoCapture(const string& filename)&#xff1b;参数&#xff1a;f…

一个Android下载网络图片显示并保存到系统相册的完整案例

文章目录 1. 案例简介1.1 效果演示 2. 工程配置3. 网络层3.1 网络接口定义3.2 Retrofit工具类 4. 主界面及完整代码4.1 完整主界面代码 ImageDownloadActivity4.2 布局文件 5. 总结 1. 案例简介 在 Android开发 中&#xff0c;下载图片保存到本地是常见的需求&#xff0c;看似…

一个简单的录音软件(利用QT录音,ffmpeg进行音频重采样,fdk-aac编码)

录音软件是一种非常有用的工具&#xff0c;可以帮助我们记录和存储语音信息。在本文中&#xff0c;我们将介绍一个简单的录音软件&#xff0c;该软件利用QT进行录音&#xff0c;使用ffmpeg进行音频重采样&#xff0c;并使用fdk-aac编码。 一、 环境介绍 1、QT版本: QT5.…

绕过微信电脑版旧版本限制,版本过低不给登录的问题

这张图&#xff0c;对于还在使用低版本微信电脑版的人很熟悉了吧&#xff01;因为微信逐步开始限制低版本的客户端了&#xff0c;导致无法登陆进去。 为什么这么多人还在使用旧版&#xff1f; 因为很多机器人、框架、HOOK版本的微信等等都是在旧版的基础上开发的&#xff0c;…

嘉立创PCB板子降层(从4层到2层实例)

降层导致的改变 走线和连接&#xff0c;若想正常设计先把要用的内容全部移动到其他层。若不使用可以按照下面方式全部删除。 删除定义使用的规则 删除在需要删除层的走线等所有内容

相同的 LLM 在「不同 GPU 上」会产生不同输出?为什么?

编者按&#xff1a; 在大语言模型(LLMs)的部署及其相关的算力扩容过程中&#xff0c;更换 GPU 是否也可能会对模型的输出产生重大影响&#xff1f;这个问题的答案对于确保 LLMs 在不同硬件环境下的一致性和可靠性至关重要。 我们今天为大家带来的这篇文章&#xff0c;作者的核心…

利用docker部署图形化工具 portainer

docker查找图形化工具 Portainer 拉取镜像 docker pull portainer/portainer启动docker UI容器 docker run -d -p 9209:9000 --name portainer --restart always -v /var/run/docker.sock:/var/run/docker.sock -v /opt/data3/mydocker/portainer_data:/data portainer/porta…

MFC多个控件组合存在显示不出来现象

MFC多个控件组合存在显示不出来现象 1、找到rc文件 &#xff0c; 右键查看代码 2、 3、将基础组件放在最前面即可

C++(week16): C++提高:(六) Qt基础

文章目录 零、课前须知一、Qt基础1.CLI与GUI2.事件驱动模型3.Qt快捷键 二、QtCreator1.Qt的安装&#xff1a;Qt框架、IDE2.Qt的六大模式3.核心模块4.布局5.Qt项目中的文件6.信号与槽机制7.添加资源&#xff1a;资源文件qrc8.main.cpp解析(1)ui文件 和 纯代码(2)按钮 信号槽机制…

在嵌入式Linux平台上使用Nginx搭建RTMP流媒体服务器

概述 Nginx是一个以高效稳定著称的高性能的HTTP和反向代理web服务器&#xff0c;它同时也是基于事件驱动开发的异步高性能跨平台服务器。Nginx-RTMP是基于Nginx框架的模块开发&#xff0c;很好地继承了Nginx的异步高性能以及扩展性好的优点。 RTMP 是 Real Time Messaging Pr…

docker 部署 ElasticSearch;Kibana

ELasticSearch 创建网络 docker network create es-netES配合Kibana使用时需要组网&#xff0c;使两者运行在同一个网络下 命令 docker run -d \ --name es \ -e "discovery.typesingle-node" \ -v /usr/local/es/data:/usr/share/elasticsearch/data \ -v /usr/…

C语言——编译与链接

目录 引言 翻译环境与运行环境 翻译环境 1.翻译环境的简述 2.编译过程 2.1 预处理&#xff08;预编译&#xff09; 2.2 编译 2.2.1 词法分析 2.2.2 语法分析 2.2.3 语义分析 2.3 汇编 3.链接 运行环境 结束语 引言 C语言编译与链接过程是理解程序如何从代码转化…

8月5日学习笔记 glibc安装与安全用户角色权限

一&#xff0c;glibc安装 https://www.mysql.com/ 官⽹ https://downloads.mysql.com/archives/community/ https://downloads.mysql.com/archives/get/p/23/file/mysql-8.0.33-li nux-glibc2.12-x86_64.tar 安装步骤 1.安装依赖库 [rootlocalhost ~]# yum list installed |g…

在vscode中使用ssh运行docker:从下载到运行全流程

首先在本机或者服务器上下载docker并运行 本文目的旨在本机下载docker并打包&#xff0c;然后在服务器上进行加载 docker -v Docker version 27.0.3, build 7d4bcd8有输出说明在运行 一、下载 在docker hub上下载docker以tensorflow为例 点击tag搜索自己想要的版本 copy命…

All-Reduce通信原语;Reduce+LayerNorm+Broadcast算子;gRPC:远程过程调用(RPC)框架;

目录 All-Reduce通信原语 定义与作用 实例说明 示例图解(以Ring算法为例) 结论 Reduce+LayerNorm+Broadcast算子 1. Reduce算子 2. LayerNorm算子 3. Broadcast算子 组合使用场景 gRPC:远程过程调用(RPC)框架 All-Reduce通信原语 是计算机科学中,特别是在分布式…

解锁成都跃享未来教育咨询抖音小店

在数字化浪潮汹涌的今天&#xff0c;教育行业的变革与创新层出不穷&#xff0c;其中&#xff0c;成都跃享未来教育咨询以其敏锐的洞察力和前瞻性的教育理念&#xff0c;在抖音平台上开设的小店&#xff0c;正悄然改变着人们的学习方式和教育资源的获取途径。本文将深入探讨成都…

骰子游戏的UML分析

一、需求分析 游戏者掷两个骰子,如果总点数是7则赢得游戏,否则为输 二、概要设计 2.1 设计用例 用例是基于某个场景(注:包括成功和失败场景,重要体现需求的边界)说明了用户如何通过系统实现实现其目标。 示例:玩游戏场景用例 用例名称:玩游戏 主要参与者: 游戏用户 前…

实时数据监控,三防平板在工业领域的应用解析

随着工业4.0时代的到来&#xff0c;数字化转型已成为各行各业的共同目标。在这一过程中&#xff0c;实时数据监控扮演着至关重要的角色&#xff0c;为企业提供数据驱动的决策支持&#xff0c;提升效率、降低成本、提高安全性。而作为移动终端设备&#xff0c;三防平板凭借其可靠…

深兰科技荣获2024年度金势奖“AI出海先锋品牌”金奖

近日&#xff0c;由金势奖组委会、凤凰网、营销国际协会等国内外知名机构、集团共同主办的“第四届未来营销大会暨锐品牌盛典”在上海举行。大会揭晓了第四届“金势奖锐品牌大赏”奖项的评选结果&#xff0c;深兰科技凭借自身在机器人产品出口和海外市场开拓等出海全球化发展方…