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
     */
    @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);
    }

三、数据库常用的六个操作,建表、删除表、增、删、改、查,其SQL语句如下所示

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<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 谢谢!

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值