前言:只要有坚强的持久心,一个庸俗平凡的人也会有成功的一天,否则即使是一个才识卓越的人,也只能遭遇失败的命运。 -----比尔盖茨
源码地址:https://github.com/FollowExcellence/SqliteDemo
SQLite是一款轻量级的关系型数据库,它的运算速度非常快,占用资源很少,通常只需要几百K的内存就足够了,因而特别适合在移动设备上使用。SQLite是一个实现了自给自足的、无服务器的、零配置的、事务性的SQL数据库引擎,并且是一个开源项目。Android上自带SQLite,因此是Android项目上常用来保存数据。
一般数据采用的固定的静态数据类型,而SQLite采用的是动态数据类型,会根据存入值自动判断。SQLite具有以下五种常用的数据类型:
NULL: 这个值为空值。
VARCHAR(n):长度不固定且其最大长度为 n 的字串,n不能超过 4000。
CHAR(n):长度固定为n的字串,n不能超过 254。
INTEGER: 值被标识为整数,依据值的大小可以依次被存储为1,2,3,4,5,6,7,8.
REAL: 所有值都是浮动的数值,被存储为8字节的IEEE浮动标记序号.
TEXT: 值为文本字符串,使用数据库编码存储(TUTF-8, UTF-16BE or UTF-16-LE).
BLOB: 值是BLOB数据块,以输入的数据格式进行存储。如何输入就如何存储,不改 变格式。
DATA :包含了 年份、月份、日期。
TIME: 包含了 小时、分钟、秒。
创建数据库表:
首先创建一个继承在SQLiteOpenHelper的类,并重写onCreate()和onUpgrade()方法。
/**
* @创建者 mingyan.su
* @创建时间 2018/9/29 16:45
* @类描述 ${TODO}数据库Helper类,必须继承自 SQLiteOpenHelper
*/
public class SQLiteHelper extends SQLiteOpenHelper {
private static final String DB_NAME = "SqliteDemo.db";
public static final String TABLE_NAME = "OpenBleLog";
public SQLiteHelper(Context context) {
/**
* 第一个参数: 上下文
* 第二个参数:数据库的名称
* 第三个参数:null代表的是默认的游标工厂
* 第四个参数:是数据库的版本号 数据库只能升级,不能降级,版本号只能变大不能变小
*/
super(context, DB_NAME, null, 1);
}
/**
* onCreate是在数据库创建的时候调用的,主要用来初始化数据表结构和插入数据初始化的记录
* 当数据库第一次被创建的时候调用的方法,适合在这个方法里面把数据库的表结构定义出来.
* 所以只有程序第一次运行的时候才会执行
* 如果想再看到这个函数执行,必须写在程序然后重新安装这个app
*
* @param sqLiteDatabase
*/
@Override
public void onCreate(SQLiteDatabase sqLiteDatabase) {
String sql = "create table if not exists " + TABLE_NAME + "(_id integer primary key autoincrement, user_id long not null, name text, address text, time text)";
sqLiteDatabase.execSQL(sql);
}
/**
* 当数据库更新的时候调用的方法
* 这个要显示出来得在上面的super语句里面版本号发生改变时才会 打印 (super(context, DB_NAME, null, 2);)
* 注意,数据库的版本号只可以变大,不能变小,假设我们当前写的版本号是3,运行,然后又改成1,运行则报错。不能变小
* 在数据库版本每次发生变化时都会把用户手机上的数据库表删除,然后再重新创建。
* 一般在实际项目中是不能这样做的,正确的做法是在更新数据库表结构时,还要考虑用户存放于数据库中的数据不会丢失。
*
* @param sqLiteDatabase
* @param oldVersion 旧版本
* @param newVersion 新版本
*/
@Override
public void onUpgrade(SQLiteDatabase sqLiteDatabase, int oldVersion, int newVersion) {
//第一次创建不需要做任何操作
String sql = "DROP TABLE IF EXISTS " + TABLE_NAME;
sqLiteDatabase.execSQL(sql);
/* if (oldVersion==2 && newVersion==3) {//升级判断,如果再升级就要再加两个判断,从1到3,从2到3
sqLiteDatabase.execSQL("ALTER TABLE " + TABLE_NAME + " ADD phone TEXT;");//新版本为2的时候,往表中增加一列,在第三版本就可以使用phone字段了
}*/
}
}
操作数据库:
然后建一个Dao类用于处理所有的数据操作方法(增删改查)。在Dao中实例化Helper处理数据:
/**
* dao类需要实例化数据库Help类,只有得到帮助类的对象我们才可以实例化 SQLiteDatabase
*
* @param context
*/
public SQliteDao(Context context) {
this.context = context;
mSqLiteHelper = new SQLiteHelper(context);
}
1.建表:
CREATE TABLE 数据表名称(字段1 类型1(长度),字段2 类型2(长度) …… );
CREATE TABLE IF NOT EXISTS 数据表名称(字段1 类型1(长度),字段2 类型2(长度) …… );
重写oncteate()方法,通常是建表的操作,由于要定制其各列的字段名及数据类型,所以仍然只能使用原始的SQL语句,通过SQLiteDatabase.execSQL(String)来执行。
@Override
public void onCreate(SQLiteDatabase sqLiteDatabase) {
String sql = "create table if not exists " + TABLE_NAME + "(_id integer primary key autoincrement, user_id long not null, name text, address text, time text)";
sqLiteDatabase.execSQL(sql);
}
2.删除表
DROP TABLE 数据表名称;
DROP TABLE IF EXISTS 数据表名称;
@Override
public void onUpgrade(SQLiteDatabase sqLiteDatabase, int oldVersion, int newVersion) {
//第一次创建不需要做任何操作
String sql = "DROP TABLE IF EXISTS " + TABLE_NAME;
sqLiteDatabase.execSQL(sql);
/* if (oldVersion==2 && newVersion==3) {//升级判断,如果再升级就要再加两个判断,从1到3,从2到3
sqLiteDatabase.execSQL("ALTER TABLE " + TABLE_NAME + " ADD phone TEXT;");//新版本为2的时候,往表中增加一列,在第三版本就可以使用phone字段了
}*/
}
上面onUpgrade()方法通常是处理一些升级操作,与传递的version参数相关,在数据库版本每次发生变化时都会把用户手机上的数据库表删除,然后再重新创建。一般在实际项目中是不能这样做的,正确的做法是在更新数据库表结构时,还要考虑用户存放于数据库中的数据不会丢失。
3.增
INSERT INTO 数据表 (字段1,字段2,字段3 …) valuess (值1,值2,值3 …);
INSERT INTO 目标数据表 SELECT * FROM 源数据表;
数据库的增和删都是针对行的,
String sql = "insert into OpenBleLog (user_id, name, address, time) values (10083, '张三', '广东省深圳市', '2018-10-15')";
db.execSQL(sql);
public long addForContentValues(OpenBleInfo userAddress) {
SQLiteDatabase writableDatabase = mSqLiteHelper.getWritableDatabase();
ContentValues contentValues = new ContentValues();
contentValues.put(COLUMNS_USERID, userAddress.getUser_id());
contentValues.put(COLUMNS_NAME, userAddress.getName());
contentValues.put(COLUMNS_ADDRESS, userAddress.getAddress());
contentValues.put(COLUMNS_TIME, userAddress.getTime());
long insert = writableDatabase.insert(SQLiteHelper.TABLE_NAME, null, contentValues);
db.close();
return insert;
}
返回值是一个long,显示数据添加在第几行,比如:连续增加了3条数据,把第三条删除后,在增加的数据是在第四行而不是第三行,因为自增长,-1表示增加失败。
给TABLE_NAME这个表中增加一行。在这一行中,把value1放到key1这一列,把value2放到key2这一列。ContentValues内部实现就是HashMap,但是两者还是有差别的,ContenValuesKey只能是String类型,Value只能存储基本类型的数据,像string,int之类的,不能存储对象这种东西。
4.删
DELETE FROM 数据表 WHERE 条件表达式;
DELETE FROM 数据表;
db.execSQL("delete from OpenBleLog where name = ?", new String[]{name});
int delete = db.delete(SQLiteHelper.TABLE_NAME, COLUMNS_NAME + " = ?", new String[]{name});
whereClause是删除条件,whereArgs是删除条件值数组
返回值是int,-1表示删除失败,0表示没有这条数据
5.改
UPDATE 数据表 SET 字段名=字段值 WHERE 条件表达式;
UPDATE 数据表 SET 字段1=值1,字段2=值2 …… 字段n=值n WHERE 条件表达式;
ContentValues contentValues = new ContentValues();
contentValues.put(COLUMNS_ADDRESS, address);
int update = db.update(SQLiteHelper.TABLE_NAME, contentValues, COLUMNS_NAME + " = ?", new String[]{name});
返回值:-1表示更新失败,0表示没有这条数据,
6.查
SELECT * FROM 数据表 WHERE 字段名=字段值 ORDER BY 字段名 [DESC];
SELECT * FROM 数据表 WHERE 字段名 LIKE '%字段值%' ORDER BY 字段名 [DESC];
SELECT TOP 10 * from 数据表 WHERE 字段名 ORDER BY 字段名 [DESC];
SELECT * FROM 数据表 WHERE 字段名 IN ('值1','值2','值3');
SELECT * FROM 数据表 WHERE 字段名 BETWEEN 值1 AND 值2;
cursor = db.query(SQLiteHelper.TABLE_NAME, COLUMNS, key + " = ?", new String[]{values}, null, null, null);
if (cursor != null && cursor.getCount() > 0) {
List addressList = new ArrayList<>();
while (cursor.moveToNext()) {
OpenBleInfo userAddress = parseDate(cursor);
addressList.add(userAddress);
}
return addressList;
返回的是一个游标Cursor。
Cursor是结果集游标,用于对结果集进行随机访问,使用moveToNext()方法可以将游标从当前行移动到下一行,如果已经移过了结果集的最后一行,返回结果为false,否则为true。另外Cursor 还有常用的moveToPrevious()方法(用于将游标从当前行移动到上一行,如果已经移过了结果集的第一行,返回值为false,否则为true )、moveToFirst()方法(用于将游标移动到结果集的第一行,如果结果集为空,返回值为false,否则为true )和moveToLast()方法(用于将游标移动到结果集的最后一行,如果结果集为空,返回值为false,否则为true 。注意:使用完成后必须将游标关闭,cursor.close();
对于像银行转账之类的操作,我们需要使用事务来保证操作的安全性,SQLite也提供了对事务的支持。
使用SQLiteDatabase的beginTransaction()方法可以开启一个事务,程序执行到endTransaction() 方法时会检查事务的标志是否为成功,如果程序执行到endTransaction()之前调用了setTransactionSuccessful() 方法设置事务的标志为成功则提交事务,如果没有调用setTransactionSuccessful() 方法则回滚事务。
/**
* 删除表中所有数据
*
* @return 删除是否成功
* String sql = "delete from OpenBleLog"
*/
public boolean deleteAll() {
SQLiteDatabase db = null;
try {
db = mSqLiteHelper.getWritableDatabase();
db.beginTransaction();//开启一个事务
String sql = "delete from " + SQLiteHelper.TABLE_NAME;
System.out.println(sql);
db.execSQL(sql);
db.setTransactionSuccessful();//调用此方法会在执行到endTransaction() 时提交当前事务,如果不调用此方法会回滚事务
return true;
} catch (Exception e) {
e.printStackTrace();
} finally {
if (db != null) {
db.endTransaction();//由事务的标志决定是提交事务,还是回滚事务
db.close();
}
}
return false;
}
getWritableDatabase()和getReadableDatabase()方法都可以获取一个用于操作数据库的SQLiteDatabase实例。但getWritableDatabase() 方法以读写方式打开数据库,一旦数据库的磁盘空间满了,数据库就只能读而不能写,倘若使用getWritableDatabase()打开数据库就会出错。getReadableDatabase()方法先以读写方式打开数据库,如果数据库的磁盘空间满了,就会打开失败,当打开失败后会继续尝试以只读方式打开数据库。
增删改查每一个方法都要得到数据库,然后操作完成后一定要关闭。db.close();
另外:数据库文件利用DDMS可以查看,在 data/data/包名/databases 目录下即可查看,如果打不开文件则需要访问权限才能打开。
至此,本文结束!
源码下载地址:https://github.com/FollowExcellence/SqliteDemo
请大家尊重原创者版权,转载请标明出处: https://blog.csdn.net/m0_37796683/article/details/83148428 谢谢!