sqlite使用可参考:https://www.runoob.com/sqlite/sqlite-tutorial.html
1、sqlite基本使用1.1、sqliteOpenHelper简介 sqliteOpenHelper是一个抽象类,用于辅助sqlite数据库 *** 作,必须实现构造方法、onCreate和onUpgrade。
(1)构造方法:
public sqliteOpenHelper(@Nullable Context context, @Nullable String name, @Nullable CursorFactory factory, int version)public sqliteOpenHelper(@Nullable Context context, @Nullable String name, @Nullable CursorFactory factory, int version, @Nullable DatabaseErrorHandler errorHandler)public sqliteOpenHelper(@Nullable Context context, @Nullable String name, int version, @NonNull sqliteDatabase.OpenParams openParams) public sqliteOpenHelper(@Nullable Context context, @Nullable String name, @Nullable CursorFactory factory, int version, int minimumSupportedVersion, @Nullable DatabaseErrorHandler errorHandler)private sqliteOpenHelper(@Nullable Context context, @Nullable String name, int version, int minimumSupportedVersion, @NonNull sqliteDatabase.OpenParams.Builder openParamsBuilder)
其中context可以传入Application的context, name为对应的数据库文件名(sqlite数据持久化需要,如果传入null, 则会创建一个内存数据库,应用结束数据会丢失), version为数据库版本,minimumSupportedVersion为数据库支持的最低版本,已存在的数据库版本低于这个版本时数据库将被删除,重新创建数据库,openParamsBuilder为数据库打开参数类sqliteDatabase.OpenParams的builder, 可配置数据库损坏监听errorHandler和用于查询时生成Cursor的cursorFactory。
(2)onCreate(sqliteDatabase db)方法
onCreate方法中一般通过sqliteDatabase类型的db,执行execsql(String sql)来实现表的创建。
(3)onUpgrade(sqliteDatabase db, int oldVersion, int newVersion)方法
oldVersion为已存在的数据库版本,newVersion为新创建的数据库版本(构造方法中传入的version),需要大于oldVersion。该方法用于数据库升级,可以添加列、修改表名等。
(4)onConfigure(sqliteDatabase db)、onopen(sqliteDatabase db)等
onConfigure在onCreate之前调用,可以启用写前日志记录或外键支持,onopen重写以执行数据库开启后的 *** 作。
当已存在的数据库版本oldVerson等于0时(表示数据库不存在),会调用onCreate方法,创建相应的表;如果oldVersion小于newVersion,会调用onUpgrade方法,执行数据库升级相关 *** 作,如果oldVersion大于newVersion,会调用onDowngrade方法(需要重写onDowngrade方法),执行数据库降级 *** 作。
1.2、数据库增、删、改、查 (1)创建sqliteOpenHelper,用于 *** 作指定数据库中的数据
新建UsersqliteHelper类,继承自sqliteOpenHelper,实现onCreate方法和onUpgrade方法,在onCreate方法中新建表,在onUpgrade中升级表。
public class UsersqliteHelper extends sqliteOpenHelper { private static final int CURRENT_VERSION = 1; private static final String CREATE_USER_table = "create table user(ID integer primary key autoincrement, " + "name char(50)" + ", age int default 18" + ")"; private static final String DROP_USER_table = "drop table if exists user"; private UsersqliteHelper(int version) { super(BaseApplication.getInstance(), "user.db", null, version); } @OverrIDe public voID onCreate(sqliteDatabase db) { db.execsql(CREATE_USER_table); } @OverrIDe public voID onUpgrade(sqliteDatabase db, int oldVersion, int newVersion) { //这里简单的删除原来的表,再新建表 db.execsql(DROP_USER_table); onCreate(db); } private static volatile UsersqliteHelper instance; public static UsersqliteHelper getInstance() { if (instance == null) { synchronized (UsersqliteHelper.class) { if (instance == null) { instance = new UsersqliteHelper(CURRENT_VERSION); } } } return instance; }}
获取 *** 作数据库的sqliteDatabase
String tablename = "user";UsersqliteHelper helper = UsersqliteHelper.getInstance();sqliteDatabase writableDatabase = helper.getWritableDatabase();
查询数据库中所有的记录,用于检查增、删、改、查结果
private voID queryAll(String tag, sqliteDatabase database) { String table = "user"; Cursor cursor = database.query(table, new String[]{"name", "ID"}, null, null, null, null, null); if (cursor == null) { Log.d("Test" + tag, "查询全部:查询得到的cursor为空"); } else if (cursor.getCount() == 0) { Log.d("Test" + tag, "查询全部:未查询到指定的数据"); cursor.close(); } else { while (cursor.movetoNext()) { String name = cursor.getString(cursor.getColumnIndex("name")); int ID = cursor.getInt(cursor.getColumnIndex("ID")); Log.d("Test" + tag, "查询全部:User[name = " + name + ", ID = " + ID + "]"); } cursor.close(); }}
(2)新增数据
//增加数据ContentValues insert = new ContentValues();insert.put("name", "张三");writableDatabase.insert(tablename, "name", insert);queryAll("增加后", writableDatabase);
Logcat中输出为:
Test增加后: 查询全部:User[name = 张三, ID = 3]
(3)查询数据
//查询数据Cursor cursor = writableDatabase.query(tablename, new String[]{"name", "ID"}, "name = ?", new String[]{"张三"}, null, null, null);if (cursor == null) { Log.d("Test", "查询得到的cursor为空");} else if (cursor.getCount() == 0) { Log.d("Test", "未查询到指定的数据"); cursor.close();} else { while (cursor.movetoNext()) { String name = cursor.getString(cursor.getColumnIndex("name")); int ID = cursor.getInt(cursor.getColumnIndex("ID")); Log.d("Test", "User[name = " + name + ", ID = " + ID + "]"); } cursor.close();}queryAll("查询后", writableDatabase);
Logcat中输出为:
Test: User[name = 张三, ID = 3]Test查询后: 查询全部:User[name = 张三, ID = 3]
(4)更新数据
//更新数据ContentValues update = new ContentValues();update.put("name", "李四");// 相当于update user set name = "李四" where name = "张三"writableDatabase.update(tablename, update, "name = ?", new String[]{"张三"}); queryAll("更新后", writableDatabase);
Logcat中输出为:
Test更新后: 查询全部:User[name = 李四, ID = 3]
(5)删除数据
//删除writableDatabase.delete(tablename, "name = ?", new String[]{"李四"});queryAll("删除后", writableDatabase);
Logcat中输出为:
Test删除后: 查询全部:未查询到指定的数据
2、sqliteDatabase增、删、改、查参数分析2.1、增 用于插入数据的方法有三个,分别是
public long insert(String table, String nullColumnHack, ContentValues values)public long insertOrThrow(String table, String nullColumnHack, ContentValues values)public long insertWithOnConflict(String table, String nullColumnHack, ContentValues initialValues, int conflictAlgorithm)
insertWithOnConflict使用conflictAlgorithm参数,指定列存在约束并且冲突时的处理,包括回滚、终止、替换等。insert方法和insertWithOrThrow都调用了insertWithOnConflict,指定了CONFliCT_NONE算法,即不做任何 *** 作。
insertWithOnconflict方法如下:
public long insertWithOnConflict(String table, String nullColumnHack, ContentValues initialValues, int conflictAlgorithm) { acquireReference(); try { StringBuilder sql = new StringBuilder(); sql.append("INSERT"); sql.append(CONFliCT_VALUES[conflictAlgorithm]); sql.append(" INTO "); sql.append(table); sql.append('('); Object[] bindArgs = null; int size = (initialValues != null && !initialValues.isEmpty()) ? initialValues.size() : 0; if (size > 0) { bindArgs = new Object[size]; int i = 0; for (String colname : initialValues.keySet()) { sql.append((i > 0) ? "," : ""); sql.append(colname); bindArgs[i++] = initialValues.get(colname); } sql.append(')'); sql.append(" VALUES ("); for (i = 0; i < size; i++) { sql.append((i > 0) ? ",?" : "?"); } } else { sql.append(nullColumnHack + ") VALUES (NulL"); } sql.append(')'); sqliteStatement statement = new sqliteStatement(this, sql.toString(), bindArgs); try { return statement.executeInsert(); } finally { statement.close(); } } finally { releaseReference(); }}
以上可以看出,该方法就是根据各参数,生成SQL语句,然后执行插入 *** 作,其中SQL语句如下: insert 参数1 into 参数2 ( 参数3 ) , 其中
参数1为插入数据存在冲突时使用的算法,为String[] CONFliCT_VALUES = new String[] {"", " OR RolLBACK ", " OR ABORT ", " OR FAIL ", " OR IGnorE ", " OR REPLACE "}中的一个,
参数2为要插入数据对应的表, 上面示例中为user,
参数3为具体的数据, 假设initialValues中有name和age两个字段(initialValues为空的情况,会插入一条数据,nullColumnHack指定的列值为null),分别为张三、30, 则参数3 为 name, age) values(?, ? , 对应的bindArgs为{"张三", 30}。
于是要执行的SQL语句为insert or replace into user ( name, age) values(?, ? ),对应的参数bindArgs为{"张三", 30},传入sqliteStatement, 调用executeInsert()方法以执行对应的插入语句。。
2.2、删 用于删除的方法有一个:
public int delete(String table, String whereClause, String[] whereArgs) { acquireReference(); try { sqliteStatement statement = new sqliteStatement(this, "DELETE FROM " + table + (!TextUtils.isEmpty(whereClause) ? " WHERE " + whereClause : ""), whereArgs); try { return statement.executeUpdateDelete(); } finally { statement.close(); } } finally { releaseReference(); } }
方法有三个参数table、whereClause、whereArgs,其中table表示要 *** 作的表名, whereClause格式类似于 ID = ? and name = ?,数组whereArgs提供占位符?对应的参数,传入sqliteStatement, 调用executeUpdateDelete以执行delete from table where ID = ? and name = ?语句,对应的参数为whereArgs。如果whereClause为空字符串或null, 则会执行delete from table,会将表中所有的数据删除。
2.3、改 用于更新的方法有两个:
public int update(String table, ContentValues values, String whereClause, String[] whereArgs)public int updateWithOnConflict(String table, ContentValues values, String whereClause, String[] whereArgs, int conflictAlgorithm)
其中update(String, ContentValues, String, String[])方法调用了updateWithOnConflict(String, ContentValues, String, String[], int), 最后一个参数指定数据冲突时的算法,和insert相关的方法中相同。
updateWithOnConflict(String, ContentValues, String, String[], int)方法如下:
public int updateWithOnConflict(String table, ContentValues values, String whereClause, String[] whereArgs, int conflictAlgorithm) { if (values == null || values.isEmpty()) { throw new IllegalArgumentException("Empty values"); } acquireReference(); try { StringBuilder sql = new StringBuilder(120); sql.append("UPDATE "); sql.append(CONFliCT_VALUES[conflictAlgorithm]); sql.append(table); sql.append(" SET "); // move all bind args to one array int setValuesSize = values.size(); int bindArgsSize = (whereArgs == null) ? setValuesSize : (setValuesSize + whereArgs.length); Object[] bindArgs = new Object[bindArgsSize]; int i = 0; for (String colname : values.keySet()) { sql.append((i > 0) ? "," : ""); sql.append(colname); bindArgs[i++] = values.get(colname); sql.append("=?"); } if (whereArgs != null) { for (i = setValuesSize; i < bindArgsSize; i++) { bindArgs[i] = whereArgs[i - setValuesSize]; } } if (!TextUtils.isEmpty(whereClause)) { sql.append(" WHERE "); sql.append(whereClause); } sqliteStatement statement = new sqliteStatement(this, sql.toString(), bindArgs); try { return statement.executeUpdateDelete(); } finally { statement.close(); } } finally { releaseReference(); } }
和insertWithOnConflict类似, 该方法也是将参数拼接成SQL语句:update 参数1 参数2 set 参数3 where 参数4, 其中:
参数1为更新数据存在冲突时使用的算法,为String[] CONFliCT_VALUES = new String[] {"", " OR RolLBACK ", " OR ABORT ", " OR FAIL ", " OR IGnorE ", " OR REPLACE "}中的一个,
参数2为要更新数据对应的表, 上面示例中为user,
参数3为具体需要更新字段拼接的字符串,假设ContentValues中有name和age两个字段,分别为张三、30, 则参数3 为 name=? , age = ? , 对应的bindArgs为{"张三", 30}。
参数4为对应的查询条件,对应String whereClause参数,类似于**ID = 20 and name =李四 **等查询条件, 以指定具体需要更新的数据。
于是,具体的SQL语句为:update or replace user set name=?, age = ? where ID = 20 and name = 李四, 对应的参数bindArgs为{"张三", 30}, 传入sqliteStatement, 调用executeUpdateDelete()方法以执行对应的更新语句。
2.4、查 (1) 使用参数的查询方法有:
public Cursor query(boolean distinct, String table, String[] columns, String selection, String[] selectionArgs, String groupBy, String having, String orderBy, String limit) public Cursor query(boolean distinct, String table, String[] columns, String selection, String[] selectionArgs, String groupBy, String having, String orderBy, String limit, CancellationSignal cancellationSignal) public Cursor query(String table, String[] columns, String selection, String[] selectionArgs, String groupBy, String having, String orderBy) public Cursor query(String table, String[] columns, String selection, String[] selectionArgs, String groupBy, String having, String orderBy, String limit)public Cursor queryWithFactory(CursorFactory cursorFactory, boolean distinct, String table, String[] columns, String selection, String[] selectionArgs, String groupBy, String having, String orderBy, String limit) public Cursor queryWithFactory(CursorFactory cursorFactory, boolean distinct, String table, String[] columns, String selection, String[] selectionArgs, String groupBy, String having, String orderBy, String limit, CancellationSignal cancellationSignal)
最上面五个方法是对最后一个方法queryWithFactory的调用,也是通过拼接SQL语句再执行来完成查询 *** 作的,方法如下:
public Cursor queryWithFactory(CursorFactory cursorFactory, boolean distinct, String table, String[] columns, String selection, String[] selectionArgs, String groupBy, String having, String orderBy, String limit, CancellationSignal cancellationSignal) { acquireReference(); try { String sql = sqlitequeryBuilder.buildqueryString( distinct, table, columns, selection, groupBy, having, orderBy, limit); return rawqueryWithFactory(cursorFactory, sql, selectionArgs, findEdittable(table), cancellationSignal); } finally { releaseReference(); }}
其中,调用了sqlitequeryBuilder的buildqueryString方法来拼接SQL语句,如下:
public static String buildqueryString( boolean distinct, String tables, String[] columns, String where, String groupBy, String having, String orderBy, String limit) { if (TextUtils.isEmpty(groupBy) && !TextUtils.isEmpty(having)) { throw new IllegalArgumentException( "HAVING clauses are only permitted when using a groupBy clause"); } if (!TextUtils.isEmpty(limit) && !slimitPattern.matcher(limit).matches()) { throw new IllegalArgumentException("invalID liMIT clauses:" + limit); } StringBuilder query = new StringBuilder(120); query.append("SELECT "); if (distinct) { query.append("disTINCT "); } if (columns != null && columns.length != 0) { appendColumns(query, columns); } else { query.append("* "); } query.append("FROM "); query.append(tables); appendClause(query, " WHERE ", where); appendClause(query, " GROUP BY ", groupBy); appendClause(query, " HAVING ", having); appendClause(query, " ORDER BY ", orderBy); appendClause(query, " liMIT ", limit); return query.toString();}
最终将SQL语句拼接成如下格式(参数1为所需查询列拼接的字符串):SELECT distinct 参数1 FROM table WHERE selection GROUP BY groupBy HAVING having ORDER BY orderBy liMIT limit。从查询语句来看,之前列出的查询方法都可以进行多表查询,示例如下:
//增加数据ContentValues values = new ContentValues();values.put("name", "张三");writableDatabase.insert("user", "name", values);writableDatabase.insert("user1", "name", values);//查询数据Cursor cursor = writableDatabase.query(true, "user,user1", new String[]{"user.name", "user.ID", "user1.name", "user1.ID"}, "user.name = ? and user1.name = ?", new String[]{"张三", "张三"}, null, null, null, null);if (cursor == null) { Log.d("Test", "查询得到的cursor为空");} else if (cursor.getCount() == 0) { Log.d("Test", "未查询到指定的数据"); cursor.close();} else { while (cursor.movetoNext()) { String name = cursor.getString(cursor.getColumnIndex("user.name")); int ID = cursor.getInt(cursor.getColumnIndex("user.ID")); String name1 = cursor.getString(cursor.getColumnIndex("user1.name")); int ID1 = cursor.getInt(cursor.getColumnIndex("user1.ID")); Log.d("Test", "name = " + name + ", ID = " + ID + ", name1 = " + name1 + ", ID1 = " + ID1); } cursor.close();}
(2)直接使用sql的查询方法有:
public Cursor rawquery(String sql, String[] selectionArgs)public Cursor rawquery(String sql, String[] selectionArgs, CancellationSignal cancellationSignal) public Cursor rawqueryWithFactory( CursorFactory cursorFactory, String sql, String[] selectionArgs, String edittable) public Cursor rawqueryWithFactory( CursorFactory cursorFactory, String sql, String[] selectionArgs, String edittable, CancellationSignal cancellationSignal)
直接通过SQL语句来进行查询,可以进行多表复合查询,sql对对应的查询语句, selectionArgs为占位符?对应的参数数组。
2.5、其他 sqliteDatabase除了增删改查之外, 还可以执行其他语句,包括创建表、删除表、重命名表、添加列等等。
public voID execsql(String sql) throws sqlException { executesql(sql, null);}public voID execsql(String sql, Object[] bindArgs) throws sqlException { if (bindArgs == null) { throw new IllegalArgumentException("Empty bindArgs"); } executesql(sql, bindArgs);}public int executesql(String sql, Object[] bindArgs) { ...}
3、sqliteDatabase事务 某种情况下,需要执行一系列 *** 作时,确保这些 *** 作同时成功,或者同时失败,数据库中能够保证这些 *** 作同时成功或同时失败的执行单元称为事务,典型的代码如下:
sqliteDatabase.beginTransaction(); try { ... sqliteDatabase.setTransactionSuccessful(); } finally { sqliteDatabase.endTransaction(); }
sqliteDatabase的beginTransaction()方法标识一个事务的开始, setTransactionSuccessful()表示增删改查等 *** 作成功,endTransaction()方法表示结束一个事务,此时修改将被提交到数据库。如果过程中产生异常,则不会调用setTransactionSuccessful(),中间的各种 *** 作将被还原。
事务开始标识有如下方法:
public voID beginTransaction() { beginTransaction(null /* transactionStatusCallback */, true);}public voID beginTransactionNonExclusive() { beginTransaction(null /* transactionStatusCallback */, false);}public voID beginTransactionWithListener(sqliteTransactionListener transactionListener) { beginTransaction(transactionListener, true);}public voID beginTransactionWithListenerNonExclusive( sqliteTransactionListener transactionListener) { beginTransaction(transactionListener, false);}private voID beginTransaction(sqliteTransactionListener transactionListener, boolean exclusive) { acquireReference(); try { getThreadSession().beginTransaction( exclusive ? sqliteSession.TRANSACTION_MODE_EXCLUSIVE : sqliteSession.TRANSACTION_MODE_IMMEDIATE, transactionListener, getThreadDefaultConnectionFlags(false /*Readonly*/), null); } finally { releaseReference(); }}
其中sqliteTransactionListener为事务执行过程监听接口,可以监测到事务具体的执行情况:onBegin、onCommit、onRoolback, 分别表示开始、提交、还原。
public interface sqliteTransactionListener { /** * Called immediately after the transaction begins. */ voID onBegin(); /** * Called immediately before commiting the transaction. */ voID onCommit(); /** * Called if the transaction is about to be rolled back. */ voID onRollback();}
总结:以上简要分析了sqliteDatabase的用法,包括增删改查等, 还有就是sqlite事务在安卓中的应用。
总结以上是内存溢出为你收集整理的Android中数据库SQLite用法解析全部内容,希望文章能够帮你解决Android中数据库SQLite用法解析所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)