文章目录
零、本讲学习目标
一、导入
二、讲解
(一)SQLite数据库
1、SQLite构成
2、SQLite数据类型
3、SQLite数据库特点
(二)使用SQLiteDatabase类操作数据库
1、创建安卓应用
2、准备图片素材
3、字符串资源文件
4、主布局资源文件
5、主界面类实现功能
6、启动应用,查看效果
7、查看数据库文件
(三)使用SQLiteDatabase类操作数据表
2、准备背景图片
3、字符串资源文件
4、主布局资源文件
5、主界面类实现功能
(1)编写代码创建或打开数据库
(2)编写代码创建表
(3)编写代码添加表记录
(4)编写代码更新表记录
(5)编写代码显示全部表记录
(6)编写代码删除全部表记录
(7)编写代码删除表
(8)编写代码删除数据库
6、SQLiteDatabase小结
(1)Activity对象提供操作数据库的方法
(2)SQLiteDatabase对象提供了操作数据表的方法
(3)SQLiteDatabase还提供了一组对表进行增删改查的方法
零、本讲学习目标
1.能使用SQLiteDatabase类操作数据库与表 2.能使用SQLiteDatabaseHelper类操作数据库与表
一、导入
无论是安卓应用还是苹果应用,都提供了本地轻量级数据库——SQLite,可以创建和删除数据库,还能对数据表进行增删改查操作。
二、讲解
(一)SQLite数据库
1、SQLite构成
SQLite由SQL编译器、内核、后端以及附件几个部分构成。SQLite通过利用虚拟机和虚拟数据库引擎(VDBE),使得调试、修改和扩展SQLite的内核变得更加方便,所有SQL语句都被编译成易读的、可以在SQLite虚拟机中执行的程序集。
SQLite的整体结构图
2、SQLite数据类型
项目
说明
NULL
空值
INTEGER
整型值
REAL
浮点值
TEXT
字符串文本
BLOB
二进制对象 [Binary Large Object]
3、SQLite数据库特点
值得一提的是,袖珍型的SQLite竟然可以支持高达2TB大小的数据库,每个数据库都是以单个文件的形式存在,这些数据都是以B-Tree的数据结构形式存储在磁盘上。 在事务处理方面,SQLite通过数据库级上的独占性和共享锁来实现独立事务处理。这意味着多个进程可以在同一时间从同一数据库读取数据,但只有一个可以写入数据。在某个进程或线程想数据库执行写操作之前,必须获得独占锁。在获得独占锁之后,其他的读或写操作将不会再发生。
SQLite采用动态数据类型,当某个值插入到数据库时,SQLite将会检查它的类型,如果该类型与关联的列不匹配,SQLite则会尝试将该值转换成该列的类型,如果不能转换,则该值将作为本身的类型存储,SQLite称这为“弱类型”。但有一个特例,如果是INTEGER PRIMARY KEY,则其他类型不会被转换,会报一个“datatype missmatch”的错误。
ACID,指数据库事务正确执行的四个基本要素的缩写。包含:原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)、持久性(Durability)。一个支持事务(Transaction)的,必需要具有这四种特性,否则在事务过程(Transaction processing)当中无法保证数据的正确性,交易过程极可能达不到交易方的要求。
(二)使用SQLiteDatabase类操作数据库
1、创建安卓应用
基于Empty Activity 模板创建安卓应用 - CreateDeleteDB
单击【Finish】按钮
2、准备图片素材
将背景图片拷贝到drawable 目录
3、字符串资源文件
创建和删除数据库
创建数据库
删除数据库
4、主布局资源文件
主布局资源文件 - activity_main.xml
查看预览效果
5、主界面类实现功能
主界面类 - MainActivity
声明常量和变量
获取应用当期数据库个数
编写代码创建数据库
编写代码删除数据库
查看完整源代码
package net.sl.create_deletedb;
import androidx.appcompat.app.AppCompatActivity;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.os.Bundle;
import android.view.View;
import android.widget.Toast;
public class MainActivity extends AppCompatActivity {
private static final String DB_NAME_PREFIX = "student"; // 数据库名前缀
private static final int MODE = Context.MODE_PRIVATE; // 文件访问模式
private int count; // 数据库计时器
private SQLiteDatabase db; // SQLite数据库对象
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// 利用布局资源文件设置用户界面
setContentView(R.layout.activity_main);
// 获取应用当前数据库个数
count = databaseList().length;
}
/**
* 创建数据库
* 数据库位置:/data/data/net.hw.create_delete_db/databases
* @param view
*/
public void doCreateDB(View view) {
// 数据库计数器累加
count++;
// 定义数据库名
String dbname = DB_NAME_PREFIX + count + ".db";
try {
// 打开或创建数据库
db = openOrCreateDatabase(dbname, MODE, null);
// 提示用户创建成功
Toast.makeText(this, "恭喜,数据库【" + dbname + "】创建成功!", Toast.LENGTH_SHORT).show();
} catch (Exception e) {
// 提示用户创建失败
Toast.makeText(this, "遗憾,数据库【" + dbname + "】创建失败!", Toast.LENGTH_SHORT).show();
}
}
/**
* 删除数据库(删除全部数据库)
*
* @param view
*/
public void doDeleteDB(View view) {
// 获取数据库名数组
String[] dbnames = databaseList();
// 判断是否有数据库可删除
if (dbnames.length > 0) {
// 遍历数组,按名称删除数据库
for (String dbname: dbnames) {
// 删除数据库
deleteDatabase(dbname);
}
// 数据库计数器归零
count = 0;
// 提示用户删除成功
Toast.makeText(this, "恭喜,数据库全部被删除!", Toast.LENGTH_SHORT).show();
} else {
// 提示用户没有数据库可删除
Toast.makeText(this, "遗憾,没有数据库可删除!", Toast.LENGTH_SHORT).show();
}
}
}
6、启动应用,查看效果
7、查看数据库文件
在设备文件浏览器里 - /data/data/net.sl.create_delete_db/databases
(三)使用SQLiteDatabase类操作数据表
1、创建安卓应用
基于Empty Activity 模板创建安卓应用 - OperateTable
单击【Finish】按钮
2、准备背景图片
将背景图片拷贝到drawable 目录
3、字符串资源文件
字符串资源文件 - strings.xml
利用SQLiteDatabase操作数据表
创建或打开数据库
创建表
添加表记录
更新表记录
显示全部表记录
删除全部表记录
删除表
删除数据库
4、主布局资源文件
主布局资源文件 - activity_main.xml
查看预览效果
5、主界面类实现功能
主界面类 - MainActivity
声明常量与变量
(1)编写代码创建或打开数据库
数据库不存在就创建,存在就打开
启动应用,查看效果
首次单击【创建或打开数据库】按钮,吐司提示创建数据库成功,再次单击该按钮,吐司提示打开数据库成功。
(2)编写代码创建表
编写代码判断表是否存在
编写代码创建表
启动应用,查看效果
创建表得先打开数据库,创建表成功之后,再次创建表,吐司提示表已经存在
(3)编写代码添加表记录
(4)编写代码更新表记录
(5)编写代码显示全部表记录
判断表存在后,才能显示全部记录
启动应用,查看效果
(6)编写代码删除全部表记录
判断数据库是否存在,判断表是否存在
启动应用,查看效果
(7)编写代码删除表
判断数据库是否存在,判断表是否存在
启动应用,查看效果
(8)编写代码删除数据库
判断数据库是否存在
启动应用,查看效果
查看完整源代码
package net.sl.opera_tetable;
import androidx.appcompat.app.AppCompatActivity;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.os.Bundle;
import android.view.View;
import android.widget.Toast;
public class MainActivity extends AppCompatActivity {
private final String DB_NAME = "student.db"; // 数据库名
private final String TABLE_NAME = "student"; // 表名
private final int MODE = Context.MODE_PRIVATE; // 访问模式
private SQLiteDatabase db; // SQLite数据库
private int id; // 学号
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// 利用布局资源文件设置用户界面
setContentView(R.layout.activity_main);
}
/**
* 创建或打开数据库
*
* @param view
*/
public void doCreateOrOpenDB(View view) {
// 判断数据库是否存在
if (databaseList().length == 0) {
// 创建数据库
db = openOrCreateDatabase(DB_NAME, MODE, null);
// 提示用户数据库创建成功
Toast.makeText(this, "恭喜,数据库【" + DB_NAME + "】创建成功!", Toast.LENGTH_LONG).show();
} else {
// 打开数据库
db = openOrCreateDatabase(DB_NAME, MODE, null);
// 提示用户数据库打开成功
Toast.makeText(this, "恭喜,数据库【" + DB_NAME + "】打开成功!", Toast.LENGTH_LONG).show();
}
}
/**
* 判断表是否存在
*
* @param tableName
* @return true 表存在;false 表不存在
*/
private boolean isTableExisted(String tableName) {
// 定义SQL字符串
String strSQL = "SELECT * FROM sqlite_master WHERE type = ? AND name = ?";
// 执行SQL查询,返回游标
Cursor cursor = db.rawQuery(strSQL, new String[]{"table", tableName});
// 判断游标里是否有记录
if (cursor.getCount() > 0) {
return true;
} else {
return false;
}
}
/**
* 创建表
*
* @param view
*/
public void doCreateTable(View view) {
// 判断数据库对象是否为空
if (db == null) {
// 判断数据库是否存在
if (databaseList().length == 0) {
Toast.makeText(this, "请创建数据库【" + DB_NAME + "】。", Toast.LENGTH_LONG).show();
} else {
Toast.makeText(this, "请打开数据库【" + DB_NAME + "】。", Toast.LENGTH_LONG).show();
}
} else {
// 判断表是否存在
if (isTableExisted(TABLE_NAME)) {
// 弹出吐司提示用户表已存在
Toast.makeText(this, "表【" + TABLE_NAME + "】已经存在!", Toast.LENGTH_LONG).show();
} else {
try {
// 定义SQL字符串
String strSQL = "CREATE TABLE " + TABLE_NAME + "(id integer, name text, gender text)";
// 执行SQL语句
db.execSQL(strSQL);
// 提示用户创建表成功
Toast.makeText(this, "创建表成功!", Toast.LENGTH_LONG).show();
} catch (SQLException e) {
// 提示用户创建表失败
Toast.makeText(this, "创建表失败!", Toast.LENGTH_LONG).show();
}
}
}
}
/**
* 获取新记录的学号
*
* @param tableName
* @return
*/
private int getNewId(String tableName) {
// 判断表是否存在
if (isTableExisted(tableName)) {
// 查询全部表记录,返回游标
Cursor cursor = db.query(tableName, null, null,
null, null, null, null);
// 移到最后一条记录
if (cursor.moveToLast()) {
// 获取最后一条记录的id
int id = cursor.getInt(0);
// 返回新记录的id
return id + 1;
}
}
return 1;
}
/**
* 添加表记录
*
* @param view
*/
public void doAddRecord(View view) {
// 判断数据库对象是否为空
if (db == null) {
// 判断数据库是否存在
if (databaseList().length == 0) {
Toast.makeText(this, "请创建数据库【" + DB_NAME + "】。", Toast.LENGTH_LONG).show();
} else {
Toast.makeText(this, "请打开数据库【" + DB_NAME + "】。", Toast.LENGTH_LONG).show();
}
} else {
// 判断表是否存在
if (isTableExisted(TABLE_NAME)) {
// 获取新记录的学号
id = getNewId(TABLE_NAME);
// 创建内容值对象
ContentValues values = new ContentValues();
// 以键值对方式添加字段数据
values.put("id", id);
values.put("name", "学生" + id);
values.put("gender", id % 2 == 1 ? "男" : "女");
// 将数据插入表中
long count = db.insert(TABLE_NAME, null, values);
if (count != -1) {
// 弹出吐司提示用户添加成功
Toast.makeText(this, "恭喜,表记录添加成功!", Toast.LENGTH_LONG).show();
} else {
// 弹出吐司提示用户添加失败
Toast.makeText(this, "恭喜,表记录添加失败!", Toast.LENGTH_LONG).show();
}
} else {
// 提示用户先创建表
Toast.makeText(this, "表【" + TABLE_NAME + "】不存在,请先创建!", Toast.LENGTH_LONG).show();
}
}
}
/**
* 返回表记录数
*
* @param tableName
* @return 表记录数
*/
private int getRecordCount(String tableName) {
// 定义SQL字符串
String strSQL = "SELECT * FROM " + tableName;
// 执行SQL,返回游标
Cursor cursor = db.rawQuery(strSQL, null);
// 返回记录数
return cursor.getCount();
}
/**
* 更新表记录
*
* @param view
*/
public void doUpdateRecord(View view) {
// 判断数据库对象是否为空
if (db == null) {
// 判断数据库是否存在
if (databaseList().length == 0) {
Toast.makeText(this, "请创建数据库【" + DB_NAME + "】。", Toast.LENGTH_LONG).show();
} else {
Toast.makeText(this, "请打开数据库【" + DB_NAME + "】。", Toast.LENGTH_LONG).show();
}
} else {
// 判断表是否存在
if (isTableExisted(TABLE_NAME)) {
// 判断是否有表记录
if (getRecordCount(TABLE_NAME) > 0) {
// 定义SQL字符串
String strSQL = "UPDATE " + TABLE_NAME + " SET name = ?, gender = ? WHERE id = ?";
try {
// 执行SQL,返回更新表记录数
db.execSQL(strSQL, new Object[]{"张晓芸", "女", 1});
// 提示用户更新记录成功
Toast.makeText(this, "恭喜,表记录更新成功!", Toast.LENGTH_LONG).show();
} catch (SQLException e) {
// 提示用户更新记录失败
Toast.makeText(this, "遗憾,表记录更新失败!", Toast.LENGTH_LONG).show();
}
} else {
// 弹出吐司提示用户没有表记录
Toast.makeText(this, "没有表记录可更新,请先添加表记录!", Toast.LENGTH_LONG).show();
}
} else {
// 提示用户先创建表
Toast.makeText(this, "表【" + TABLE_NAME + "】不存在,请先创建!", Toast.LENGTH_LONG).show();
}
}
}
/**
* 显示全部表记录
*
* @param view
*/
public void doDisplayAllRecords(View view) {
// 判断数据库对象是否为空
if (db == null) {
// 判断数据库是否存在
if (databaseList().length == 0) {
Toast.makeText(this, "请创建数据库【" + DB_NAME + "】。",
Toast.LENGTH_LONG).show();
} else {
Toast.makeText(this, "请打开数据库【" + DB_NAME + "】。",
Toast.LENGTH_LONG).show();
}
} else {
// 判断表是否存在
if (isTableExisted(TABLE_NAME)) {
// 判断表里是否有记录
if (getRecordCount(TABLE_NAME) > 0) {
// 定义SQL字符串
String strSQL = "SELECT * FROM " + TABLE_NAME;
// 执行SQL,返回游标
Cursor cursor = db.query(TABLE_NAME, null, null,
null, null, null, null);
// 定义字符串生成器
StringBuilder builder = new StringBuilder();
// 遍历游标对象(记录集)
while (cursor.moveToNext()) {
// 将每条记录信息组合之后添加到字符串生成器
builder.append(cursor.getInt(0) + " "
+ cursor.getString(1) + " "
+ cursor.getString(2) + " ");
}
// 弹出吐司显示全部学生记录
Toast.makeText(this, "全部表记录\n" + builder.toString(),
Toast.LENGTH_LONG).show();
} else {
// 弹出吐司提示用户没有表记录
Toast.makeText(this, "没有表记录可显示,请先添加表记录!",
Toast.LENGTH_LONG).show();
}
} else {
// 提示用户先创建表
Toast.makeText(this, "表【" + TABLE_NAME + "】不存在,请先创建!",
Toast.LENGTH_LONG).show();
}
}
}
/**
* 删除全部表记录(三个层面的判断)
*
* @param view
*/
public void doDeleteAllRecords(View view) {
// 判断数据库对象是否为空
if (db == null) {
// 判断数据库是否存在
if (databaseList().length == 0) {
Toast.makeText(this, "请创建数据库【" + DB_NAME + "】。",
Toast.LENGTH_LONG).show();
} else {
Toast.makeText(this, "请打开数据库【" + DB_NAME + "】。",
Toast.LENGTH_LONG).show();
}
} else {
// 判断表是否存在
if (isTableExisted(TABLE_NAME)) {
// 判断是否有表记录
if (getRecordCount(TABLE_NAME) > 0) {
// 定义SQL字符串
String strSQL = "DELETE FROM " + TABLE_NAME;
try {
// 执行SQL,删除表记录
db.execSQL(strSQL);
// 提示用户删除表记录成功
Toast.makeText(this, "全部表记录已删除!", Toast.LENGTH_LONG).show();
} catch (SQLException e) {
// 提示用户删除表记录失败
Toast.makeText(this, "删除表记录失败!", Toast.LENGTH_LONG).show();
}
} else {
// 弹出吐司提示用户没有表记录
Toast.makeText(this, "没有表记录可删除,请先添加表记录!",
Toast.LENGTH_LONG).show();
}
} else {
// 提示用户先创建表
Toast.makeText(this, "表【" + TABLE_NAME + "】不存在,请先创建!",
Toast.LENGTH_LONG).show();
}
}
}
/**
* 删除表
*
* @param view
*/
public void doDeleteTable(View view) {
// 判断数据库对象是否为空
if (db == null) {
// 判断数据库是否存在
if (databaseList().length == 0) {
Toast.makeText(this, "请创建数据库【" + DB_NAME + "】。",
Toast.LENGTH_LONG).show();
} else {
Toast.makeText(this, "请打开数据库【" + DB_NAME + "】。",
Toast.LENGTH_LONG).show();
}
} else {
// 判断表是否存在
if (isTableExisted(TABLE_NAME)) {
// 定义SQL字符串
String strSQL = "DROP TABLE " + TABLE_NAME;
try {
// 执行SQL,删除表
db.execSQL(strSQL);
// 提示用户表删除成功
Toast.makeText(this, "表删除成功!", Toast.LENGTH_LONG).show();
} catch (SQLException e) {
// 提示用户表删除失败
Toast.makeText(this, "表删除失败!", Toast.LENGTH_LONG).show();
}
} else {
// 提示用户先创建表
Toast.makeText(this, "表【" + TABLE_NAME + "】不存在,请先创建!",
Toast.LENGTH_LONG).show();
}
}
}
/**
* 删除数据库
*
* @param view
*/
public void doDeleteDB(View view) {
// 判断数据库是否存在
if (databaseList().length == 0) {
// 提示用户没有数据库
Toast.makeText(this, "没有数据库可删除!", Toast.LENGTH_LONG).show();
} else {
// 判断数据库删除是否成功
if (deleteDatabase(DB_NAME)) {
// 提示用户删除成功
Toast.makeText(this, "数据库【" + DB_NAME + "】删除成功!",
Toast.LENGTH_LONG).show();
} else {
// 提示用户删除失败
Toast.makeText(this, "数据库【" + DB_NAME + "】删除失败!",
Toast.LENGTH_LONG).show();
}
}
}
}
6、SQLiteDatabase小结
(1)Activity对象提供操作数据库的方法
方法
作用
databaseList()
获取数据库名称数组
openOrCreateDatabase(String name, int mode, CursorFactory factory)
打开或创建数据库
deleteDatabase(String name)
删除数据库
(2)SQLiteDatabase对象提供了操作数据表的方法
executeSQL(),需要传入一个操作数据标的字符串参数。
rawQuery()方法要返回一个Cursor对象,有点类似于JDBC里的结果集(ResultSet)。
Cusor对象提供了一些移动记录指针的方法:moveToFirst()、moveToLast、moveToNext()、moveToPrevious()、move()、moveToPosition()。
如果我们要遍历游标集,那么我们会利用while循环与moveToNext()方法来处理。
(3)SQLiteDatabase还提供了一组对表进行增删改查的方法
方法
代码
insert()
db.insert(TABLE_NAME, null, values);
delete()
db.delete(TABLE_NAME, null, null);
update()
db.update(TABLE_NAME, values, “id = ?”, new String[] { “1” });
query()
cursor = db.query(TABLE_NAME, null, null, null, null, null, null);