【Android】数据存储之SQLite数据库知识总结

news2024/9/21 18:32:15

文章目录

  • SQL
    • 数据类型
    • 创建表格
    • 删除表格
    • 修改表格
  • 数据库管理器SQLiteDatabase
    • 数据库的创建与删除
  • SQLiteOpenHelper
    • 使用步骤
      • 新建数据库操作类
      • 增删改查方法
      • 使用 SQLite 数据库
      • 版本更新
  • 相关知识点
    • ContentValues 类
    • Cursor

SQL

SQL本质上是一种编程语言,它的学名叫作"结构化查询语言”(全称为structured QueryLanguage,简称SQL)。不过SQL语言并非通用的编程语言,它专用于数据库的访问和处理,更像是一种操作命令,所以常说SQL语句而不说SQL代码。

数据类型

SQLite 主要支持以下几种数据类型:

  • INTEGER:用于存储整型数据,通常用于存储布尔值(0 表示 false1 表示 true)。
  • REAL:用于存储浮点数。
  • TEXT:用于存储字符串数据。
  • BLOB:用于存储二进制大对象。

创建表格

CREATE IF NOT EXISTS 表格名称;

CREATE TABLE IF NOT EXISTS table_name (
    column1 datatype constraints,
    column2 datatype constraints,
    ...
);

删除表格

DROP TABLE IF EXISTS user_info

修改表格

ALTER TABLE user info ADD COLUMN phone VARCHAR;

数据库管理器SQLiteDatabase

QLiteDatabase是SQLite的数据库管理类,它提供了若干操作数据表的API

  • 管理类,用于数据库层面的操作
  1. openDatabase:打开指定路径的数据库,
  2. isOpen:判断数据库是否已打开。
  3. close:关闭数据库。
  4. getVersion:获取数据库的版本号。
  5. setVersion:设置数据库的版本号,
  • 事务类,用于事务层面的操作。
  1. beginTransaction:开事务。
  2. setTransactionSuccessful:设置事务的成功标志。
  3. endTransaction:结束事务。
  • 数据处理类,用于数据表层面的操作。
  1. execSQL:执行拼接好的SQL控制语句。
  2. delete:删除符合条件的记录。
  3. update:更新符合条件的记录。
  4. insert:插入一条记录。
  5. query:执行查询操作,返回结果集的游标。
  6. rawQuery:执行拼接好的SQL查询语句,返回结果集的游标。

数据库的创建与删除

使用openOrCreateDatabasedeleteDatabase

image-20240731161828251

public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    private String mDatabaseName;
    private TextView tv1;
    private Button btn1;
    private Button btn2;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
       
        btn1 = findViewById(R.id.button1);
        btn2 = findViewById(R.id.button2);
        tv1 = findViewById(R.id.textView1);
        btn1.setOnClickListener(this);
        btn2.setOnClickListener(this);
        
        //生成数据库完整路径
        mDatabaseName = getFilesDir() + "/test.db";
    }

    @Override
    public void onClick(View v) {
        String desc;
        if (v.getId() == R.id.button1) {
            //创建或打开数据库,不存在就创建
            SQLiteDatabase db = openOrCreateDatabase(mDatabaseName, Context.MODE_PRIVATE, null);
            desc = String.format("数据库%s创建%s", db.getPath(), (db == null) ? "失败" : "成功");
            tv1.setText(desc);
        } else if (v.getId() == R.id.button2) {
            boolean result = deleteDatabase(mDatabaseName);
            desc = String.format("数据库%s删除%s", mDatabaseName, (result) ? "成功" : "失败");
            tv1.setText(desc);
        }
    }
}

SQLiteOpenHelper

SQLiteOpenHelper类:用于创建或打开数据库的辅助类
SQLiteOpenHelper类是一个抽象类,包含两个重要的方法:

  • onCreate(SQLiteDatabase db):新建数据库时调用

  • onUpgrade(SQLiteDatabase db,int oldVersion,int newVersion):数据库版本升级时调用

image-20240730201510116

使用步骤

  1. 新建一个继承自SQLiteOpenHelper的数据库操作类,提示重写onCreateonUpgrade两个方法
  2. 封装保证数据库安全的必要方法。
  3. 提供对表记录进行增加、删除、修改、查询的操作方法。

新建数据库操作类

实现效果:

Screenshot_2024-07-31-19-13-42-327_com.example.sq

public class UserDBHelper extends SQLiteOpenHelper {
    private static final String DB_NAME = "user.db";
    private static final int DB_VERSION = 1;

    public UserDBHelper(@Nullable Context context, @Nullable String name, @Nullable SQLiteDatabase.CursorFactory factory, int version) {
        super(context, DB_NAME, null, DB_VERSION);
        // 该类的构造方法由于参数太多,我们可以在`super()`中传入自己设置的固定参数
        // context: 上下文对象,用于访问应用环境
        // DB_NAME: 数据库名称
        // null: 游标工厂,可以为null,表示使用默认的游标工厂
        // DB_VERSION: 数据库版本号,用于管理数据库的版本和升级
    }

    // 创建数据库,执行建表语句
    @Override
    public void onCreate(SQLiteDatabase db) {
        String sql = "";
        db.execSQL(sql);
    }

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

进一步补充:

public class UserDBHelper extends SQLiteOpenHelper {
    private static final String DB_NAME = "user.db";
    private static final String TABLE_NAME = "user_info";
    private static final int DB_VERSION = 1;
    private static UserDBHelper mHelper = null;
    private SQLiteDatabase mRDB = null;
    private SQLiteDatabase mWDB = null;


    private UserDBHelper(Context context) {
        super(context, DB_NAME, null, DB_VERSION);
        // 该类的构造方法由于参数太多,我们可以在`super()`中传入自己设置的固定参数
        // context: 上下文对象,用于访问应用环境
        // DB_NAME: 数据库名称
        // null: 游标工厂,可以为null,表示使用默认的游标工厂
        // DB_VERSION: 数据库版本号,用于管理数据库的版本和升级
    }

    //利用单例模式获取数据库帮助器的唯一实例
    public static UserDBHelper getInstance(Context context) {
        if (mHelper == null) {
            mHelper = new UserDBHelper(context);
        }
        return mHelper;
    }

    // 打开数据库的读链接
    public SQLiteDatabase openReadLink() {
        if (mRDB == null || !mRDB.isOpen()) {
            mRDB = mHelper.getReadableDatabase();
        }
        return mRDB;
    }

    // 打开数据库的写链接
    public SQLiteDatabase openWriteLink() {
        if (mWDB == null || !mWDB.isOpen()) {
            mWDB = mHelper.getWritableDatabase();
        }
        return mWDB;
    }

    //关闭数据库链接
    public void closeLink() {
        if (mWDB != null && mWDB.isOpen()) {
            mWDB.close();
            mWDB = null;
        }
        if (mRDB != null && mRDB.isOpen()) {
            mRDB.close();
            mRDB = null;
        }
    }

    // 创建数据库,执行建表语句
    @Override
    public void onCreate(SQLiteDatabase db) {
        String sql = "CREATE TABLE IF NOT EXISTS " + TABLE_NAME + " (" +
                "id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, " +
                "name TEXT NOT NULL, " +
                "age INTEGER NOT NULL, " +
                "height REAL NOT NULL, " +
                "weight REAL NOT NULL);";
        db.execSQL(sql);
    }

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

增删改查方法

public class UserDBHelper extends SQLiteOpenHelper {
    private static final String DB_NAME = "user.db";
    private static final String TABLE_NAME = "user_info";
    private static final int DB_VERSION = 1;
    private static UserDBHelper mHelper = null;
    private SQLiteDatabase mRDB = null;
    private SQLiteDatabase mWDB = null;


    private UserDBHelper(Context context) {
        super(context, DB_NAME, null, DB_VERSION);
        // 该类的构造方法由于参数太多,我们可以在`super()`中传入自己设置的固定参数
        // context: 上下文对象,用于访问应用环境
        // DB_NAME: 数据库名称
        // null: 游标工厂,可以为null,表示使用默认的游标工厂
        // DB_VERSION: 数据库版本号,用于管理数据库的版本和升级
    }

    //利用单例模式获取数据库帮助器的唯一实例
    public static UserDBHelper getInstance(Context context) {
        if (mHelper == null) {
            mHelper = new UserDBHelper(context);
        }
        return mHelper;
    }

    // 打开数据库的读链接
    public SQLiteDatabase openReadLink() {
        if (mRDB == null || !mRDB.isOpen()) {
            mRDB = mHelper.getReadableDatabase();
        }
        return mRDB;
    }

    // 打开数据库的写链接
    public SQLiteDatabase openWriteLink() {
        if (mWDB == null || !mWDB.isOpen()) {
            mWDB = mHelper.getWritableDatabase();
        }
        return mWDB;
    }

    //关闭数据库链接
    public void closeLink() {
        if (mWDB != null && mWDB.isOpen()) {
            mWDB.close();
            mWDB = null;
        }
        if (mRDB != null && mRDB.isOpen()) {
            mRDB.close();
            mRDB = null;
        }
    }


    // 创建数据库,执行建表语句
    @Override
    public void onCreate(SQLiteDatabase db) {
        String sql = "CREATE TABLE IF NOT EXISTS " + TABLE_NAME + " (" +
                "id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, " +
                "name TEXT NOT NULL, " +
                "age INTEGER NOT NULL, " +
                "height REAL NOT NULL, " +
                "weight REAL NOT NULL);";
        db.execSQL(sql);
    }

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

    public long insert(User user) {
        ContentValues values = new ContentValues();
        values.put("name", user.getName());
        values.put("age", user.getAge());
        values.put("height", user.getHeight());
        values.put("weight", user.getWeight());
        return mWDB.insert(TABLE_NAME, null, values);
    }

    public long delete(String name) {

        return mWDB.delete(TABLE_NAME, "name = ?", new String[]{name});
    }

    public long update(User user) {
        ContentValues values = new ContentValues();
        values.put("name", user.getName());
        values.put("age", user.getAge());
        values.put("height", user.getHeight());
        values.put("weight", user.getWeight());
        return mWDB.update(TABLE_NAME, values, "name = ?", new String[]{user.getName()});
    }

    public List<User> queryAll() {
        List<User> list = new ArrayList<>();
        Cursor cursor = mRDB.query(TABLE_NAME, null, null, null, null, null, null);
        while(cursor.moveToNext()){
            User user = new User();
            user.setId(cursor.getInt(0));
            user.setName(cursor.getString(1));
            user.setAge(cursor.getInt(2));
            user.setHeight(cursor.getLong(3));
            user.setWeight(cursor.getFloat(4));
            list.add(user);
        }
        return list;
    }
}

使用 SQLite 数据库

public class SecondActivity extends AppCompatActivity implements View.OnClickListener {

    private EditText editName, editAge, editHeight, editWeight;
    private Button btnAdd, btnDelete, btnUpdate, btnQuery;
    private SQLiteDatabase db;
    private UserDBHelper mDBHelper;
    private TextView textView2;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_second);

        textView2 = findViewById(R.id.textView2);

        editName = findViewById(R.id.editName);
        editAge = findViewById(R.id.editAge);
        editHeight = findViewById(R.id.editHeight);
        editWeight = findViewById(R.id.editWeight);

        btnAdd = findViewById(R.id.buttonAdd);
        btnDelete = findViewById(R.id.buttonDelete);
        btnUpdate = findViewById(R.id.buttonUpdate);
        btnQuery = findViewById(R.id.buttonQuery);

        btnAdd.setOnClickListener(this);
        btnDelete.setOnClickListener(this);
        btnUpdate.setOnClickListener(this);
    }

    @Override
    protected void onStart() {
        super.onStart();
        //获得数据库帮助器示例
        mDBHelper = UserDBHelper.getInstance(this);
        //打开数据库帮助器读写连接
        mDBHelper.openWriteLink();
        mDBHelper.openReadLink();
    }

    @Override
    protected void onStop() {
        super.onStop();
        // 关闭数据库帮助器读写连接
        mDBHelper.closeLink();
    }

    @Override
    public void onClick(View v) {
        String name = editName.getText().toString();
        int age = Integer.parseInt(editAge.getText().toString());
        long height = Long.parseLong(editHeight.getText().toString());
        float weight = Float.parseFloat(editWeight.getText().toString());


        if (v.getId() == R.id.buttonAdd) {
            User user = new User(name, age, height, weight);
            if (mDBHelper.insert(user) > 0) {
                Toast.makeText(this, "添加成功", Toast.LENGTH_SHORT).show();
            }
        } else if (v.getId() == R.id.buttonDelete) {
            if (mDBHelper.delete(name) > 0) {
                Toast.makeText(this, "删除成功", Toast.LENGTH_SHORT).show();
            }
        } else if (v.getId() == R.id.buttonUpdate) {
            User user = new User(name, age, height, weight);
            if (mDBHelper.update(user) > 0) {
                Toast.makeText(this, "修改成功", Toast.LENGTH_SHORT).show();
            }
        }
    }

    public void query(View view) {
        List<User> userList = mDBHelper.queryAll();
        StringBuilder sb = new StringBuilder();
        for (User user : userList) {
            sb.append(user.toString());
            sb.append("\n");
        }
        textView2.setText(sb.toString());
        Toast.makeText(this, "查询成功", Toast.LENGTH_SHORT).show();
    }
}

版本更新

onUpgrade 方法是 SQLiteOpenHelper 类中的一个回调方法,用于处理数据库版本升级时的逻辑。每当你更新数据库的版本号时(通过改变 DB_VERSION),这个方法都会被调用,以便你可以对数据库进行必要的升级操作。

@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
    // 这里编写数据库升级的代码
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
    if (oldVersion < 2) {
        // 在版本 2 中添加一个新列
        String sql = "ALTER TABLE " + TABLE_NAME + " ADD COLUMN password VARCHAR";
        db.execSQL(sql);
    }
    // 如果有更多的版本升级逻辑,可以继续添加 else if 或其他条件
}

当改变 SQLiteOpenHelperDB_VERSION 常量并重新启动应用时,onUpgrade 方法将会被调用。

private static final int DB_VERSION = 2; // 更新版本号

相关知识点

ContentValues 类

ContentValues类用于存储一组键值对,其中每个键(key)对应一个值(value),通常用于插入或更新数据库中的记录。

SQLiteDatabase类中,insert方法的签名如下:

public long insert(String table, String nullColumnHack, ContentValues values)

values:包含要插入的数据的ContentValues对象。每个键是列名,每个值是对应列的值。

// 创建一个ContentValues对象
ContentValues values = new ContentValues();
values.put("name", "John Doe"); // 设置列“name”的值
values.put("age", 30);          // 设置列“age”的值

getXxx()put()

Cursor

数据结构,用于访问数据库查询结果的数据集合。它主要用于从ContentProvider中读取数据,也可以用于直接与SQLite数据库交互。Cursor对象提供了一种机制,可以按行逐条读取数据,并从中获取具体的字段值。

  1. 特点

数据集合Cursor表示数据库查询结果中的行集合,每行表示一条记录。

定位:可以使用Cursor的方法来定位到特定的行。常用的方法包括moveToFirst(), moveToNext(), moveToLast(), 和 moveToPosition(int position)

列名和数据类型:在访问数据时,你需要知道每一列的名称或索引,以便正确地获取数据。你还需要知道列的数据类型,以便适当地转换数据类型。

随机访问Cursor支持在数据集中随机访问,允许你通过行号(索引)来获取数据。

  1. 主要方法
  • 移动游标
    • moveToFirst(): 将游标移动到结果集的第一行。如果结果集为空,则返回false
    • moveToNext(): 将游标移动到下一行。如果已到达结果集的末尾,则返回false
  • 读取数据
    • getString(int columnIndex): 获取指定列索引的字符串数据。
    • getInt(int columnIndex): 获取指定列索引的整数数据。
  • 列信息
    • getColumnIndex(String columnName): 根据列名获取列索引。
    • getColumnName(int columnIndex): 根据列索引获取列名。
    • getColumnCount(): 获取结果集中列的数量。
    • getCount(): 获取结果集中的行数。
  • 关闭游标
    • close(): 关闭Cursor对象,释放相关资源。应在完成对Cursor的操作后调用。

image-20240730200227483



感谢您的阅读
如有错误烦请指正


参考:

  1. 67-SQL基本语法_哔哩哔哩_bilibili

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

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

相关文章

pc端微信小程序接口抓包-2024最新方法

工具下载及安装 抓包工具&#xff08;charles、burpsuite之类&#xff09;代理工具(这里以proxifier为例&#xff0c;无需破解版&#xff0c;网上有公开的注册码) 配置 1、抓包工具配置&#xff08;这里以burpsuite为例&#xff09; 设置代理监听配置地址和端口&#xff0c;…

【QIIME2】细菌16s数据库_Greengenes

文章目录 下载Greengenes数据库在QIIME2中使用导入QIIME2中提取引用读取训练分类器测试分类器导出结果生成可视化文件 由于Bugbase功能注释时&#xff0c;输入的OTU表需经Greengenes注释&#xff08;且由于时间原因须是第一版&#xff09;&#xff0c;故尝试使用Greengenes对16…

探索Python网络自动化的宝库:Paramiko的秘密

文章目录 探索Python网络自动化的宝库&#xff1a;Paramiko的秘密第一部分&#xff1a;背景介绍为什么选择Paramiko&#xff1f;Paramiko能做什么&#xff1f;接下来... 第二部分&#xff1a;Paramiko是什么&#xff1f;第三部分&#xff1a;如何安装Paramiko&#xff1f;第四部…

Java OOP世界之多态

多态的概念 通俗来说&#xff0c;就是多种形态&#xff0c;具体点就是去完成某个行为&#xff0c;当不同的对象去完成时会产生出不同的状态。同一件事情&#xff0c;发生在不同对象身上&#xff0c;就会产生不同的结果。比如之前讲类和对象的时候举的猫狗的栗子&#xff0c;这…

代码随想录算法训练营第35天|01背包理论基础、01背包理论基础(滚动数组)、416. 分割等和子集

打卡Day35 1.01背包理论基础2.01背包理论基础&#xff08;滚动数组&#xff09;3.416. 分割等和子集 1.01背包理论基础 题目链接&#xff1a;01背包理论基础 文档讲解&#xff1a; 代码随想录 01背包&#xff1a; 有n件物品和一个最多能背重量为w 的背包。第i件物品的重量是we…

Studying-代码随想录训练营day50| 图论理论基础、深搜理论基础、98. 所有可达路径、广搜理论基础

第50天&#xff0c;图论开始&#xff01;最后的刷题冲刺&#xff01;&#x1f4aa;(ง •_•)ง&#xff0c;编程语言&#xff1a;C 目录 图论理论基础 图的基本概念 图的种类 度 连通性 连通图&#xff08;无向图概念&#xff09; 强连通图&#xff08;有向图概念&…

全局统一的异常处理方案

1. 在Common包中统一定义异常处理类 2. 在common包中定义异常拦截器 ExceptionHandler&#xff08;BusinessException.class&#xff09;:表示要拦截的异常类型为BusinessException 3. 在自己的项目中使用这个全局异常拦截器 继承CommonControllerAdvice并且配上ControllerAd…

MySQL数据库-事务

一、什么是事务 1.概念 事务&#xff08;Transaction&#xff09;&#xff1a;一个最小的不可再分的工作单元&#xff0c;一个事务对应一个完整的业务&#xff0c;一个完整的业务需要批量的DML(insert、update、delete)语句共同联合完成&#xff0c;事务只针对DML语句。 数据…

天气曲线echarts

1. 用多x轴实现日期&#xff0c;图标&#xff0c;控制定位固定显示高度 2.背景遮罩抛开echarts另外用div 3.设置grid的offset控制温度折线的范围 html <div class"right_bottom"><basicEchartsstyle"height: 400px; width: 1200px":option"c…

在Windows上用虚拟机安装统信UOS专业版教程

事情的起因 就是我想要一台华为电脑&#xff0c;然后上网搜索选购攻略。然后看到了一个新闻&#xff0c;就是英特尔&#xff0c;高通对华为停止供应&#xff0c;然后华为要研发自己的CPU操作系统 然后我也不了解&#xff0c;继续搜索&#xff0c;就好像是这个操作系统 统信UO…

【轨物推荐】康波、世界体系与创新范式:中国如何引爆新一轮产业革命

原创 邵宇、陈达飞 新财富 2019年12月31日 22:13 中美关系近两年备受关注&#xff0c;在诸多方面各方都已经形成了共识&#xff0c;但竞争博弈的结局富有争议性。当靠事物太近的时候&#xff0c;反而很难看清楚其面貌&#xff0c;使用康德拉季耶夫周期&#xff08;简称“康波”…

来自工业界的开源知识库 RAG 项目结构化文件解析方案比较

背景介绍 在过去实践 RAG 的过程中&#xff0c;深刻体会到 RAGFlow 提出的 "Quality in, quality out", 只有高质量的文件处理才能获得良好的 RAG 效果。 RAG 的第一步是对文件进行解析&#xff0c;由于 Embedding 和 LLM 模型的长度限制&#xff0c;往往需要将解析…

Python批量下载音乐功能

Python批量下载音乐功能 Python批量下载音乐,调用API接口,同时下载歌曲和歌词 先安排一下要用的模块&#xff0c;导入进来。 import re import json import requests目录结构 下载音乐 Awking_Class.pymusic.txt 文件文件写的是音乐名字,使用换行分割 new_music 注意这个 ne…

[极客大挑战 2019]Secret File-web

打开题目 查看源码 直接访问Archive_room.php 第二个页面是个点击框&#xff0c;这里bp抓包确认&#xff1b;若是直接SECRET&#xff0c;会跳到end.php 直接访问secr3t.php 代码审计一下 playload&#xff1a;secr3t.php?fileflag.php 改为php协议读取权限 secr3t.php?f…

CAPL使用结构体的方式组装一条DoIP车辆声明消息(方法1)

如果你参加过我的《CAPL编程系统性课程》,你就结构体类型天然就能表示报文结构,用结构体表示报文虽然麻烦,但灵活度更高。 我们今天试着用结构体类型表示DoIP车辆声明消息的DoIP报头,然后组装一条DoIP消息发送出去。 DoIP消息结构如下: DoIP车辆声明消息结构如下: /**…

SPSSAU | Power功效分析之线性回归

Power功效分析常用于实验研究时样本量的计算&#xff08;或功效值计算&#xff09;&#xff0c;如果是涉及线性回归相关的回归系数差异计算时&#xff0c;SPSSAU共提供三种情况时的Power功效分析&#xff0c;具体如下表格所述&#xff1a; 名词说明R 方值线性回归时R 方值或者…

大数据信用查询什么样的平台比较靠谱?

随着互联网的发展和普及&#xff0c;大数据技术逐渐应用到各行各业中&#xff0c;其中之一就是信用查询领域&#xff0c;大数据信用查询平台能够为用户提供全面、准确的大数据信用评估&#xff0c;然而&#xff0c;由于市场上出现了许多不同的大数据信用查询平台&#xff0c;我…

NICE Seminar(2022-1-23)基于进化优化的鲁棒区间搜索(华东理工大学堵威博士)

论文题目&#xff1a;Searching for Robustness Intervals in Evolutionary Robust Optimization 关于非支配解附近较高质量解搜集的工作。