android 使用SQLite数据库详解
前言:只要有坚强的持久心,一个庸俗平凡的人也会有成功的一天,否则即使是一个才识卓越的人,也只能遭遇失败的命运。 -----比尔盖茨
一、SQL数据库介绍
源码地址: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: 包含了 小时、分钟、秒。
二、SQLite的使用
创建数据库表:
首先创建一个继承在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*/@Overridepublic 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 新版本*/@Overridepublic 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到3sqLiteDatabase.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);}
三、数据库常用的六个操作,建表、删除表、增、删、改、查,其SQL语句如下所示
1.建表:
CREATE TABLE 数据表名称(字段1 类型1(长度),字段2 类型2(长度) …… );CREATE TABLE IF NOT EXISTS 数据表名称(字段1 类型1(长度),字段2 类型2(长度) …… );
重写oncteate()方法,通常是建表的操作,由于要定制其各列的字段名及数据类型,所以仍然只能使用原始的SQL语句,通过SQLiteDatabase.execSQL(String)来执行。
@Overridepublic 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 数据表名称;
@Overridepublic 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到3sqLiteDatabase.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<OpenBleInfo> addressList = new ArrayList<>();while (cursor.moveToNext()) {OpenBleInfo userAddress = parseDate(cursor);addressList.add(userAddress);}return addressList;
返回的是一个游标Cursor。
四、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;}
六、SQLiteDatabase
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 谢谢!