AndroidSQLite 中的批量insert 、update 操作
⼀、新增
SQLite 中的新增默认是单个事务控制的,⼀次新增就是⼀次数据库操作,⼀次事务。如果⼏千次for 循环操作,必然存在效率问题。下⾯代码是通过事务控制的⽅式提升效率:尽量别⽤下⾯的SQL 语法,在部分机型上⾯会报错。(⼩⽶、三星S3)。上⾯的写法已经可以满⾜需要了……
⼆、批量修改
需求的出现:⽐如存在N 个聊天圈⼦,圈⼦中有N 个成员。每次进⼊圈⼦的时候后台线程下载圈⼦成员最新数据,并更新数据库。这时候存在三个表:圈⼦,圈⼦-成员关系表,⽤户表。
⽤户表是所有圈⼦的⽤户,保存的时候需要判断是否存在,存在就新增,否则修改部分数据。(因为⽤户带有详细资料,⽽圈⼦成员返回的只有名字、账号、头像三个字段,不能⽤上⾯的⽅法先删除所有数据,然后批量新增)
SQL 关键写法如下(重点是SQLiteDatabase.insertWithOnConflict 的
public void addList(List<GroupMember> listMember) {
StringBuffer sbSQL = new StringBuffer();
SQLiteDatabase db = super .getDatabase ();
db .beginTransaction ();
for (int i = 0; i < listMember.size(); i++) {
GroupMember groupMember = listMember .get (i);
if(i == 0) {
// 根据当前⽤户id 和圈⼦id 删除圈⼦成员 del(groupMember .getUserId (), groupMember .getGroupId ());// 第⼀次新增的时候删除历史数据 } if(i != 0) { sbSQL .delete (0, sbSQL .length ()); } sbSQL .append (" INSERT INTO ").append (TABLE).append (" (user_id, group_id, member_id, role_id) VALUES"); sbSQL .append (" (").append (groupMember .getUserId ()) .append (",").append (groupMember .getGroupId ()) .append (",").append (groupMember .getMemberId ()) .append (",").append (groupMember .getRole ()) .append (");");
db .execSQL (sbSQL .toString ());
}
db .setTransactionSuccessful ();
db .endTransaction ();
}
123456789101112131415161718192021222324
INSERT INTO table (column1, column2) VALUES (val1, val2), (val1, val2)
1
关键的⼀个地⽅:部分参数介绍(忽略参数table 和initialValues 了,这个⼤家都知道吧 - -):
1) nullColumnHack :当values 参数为空或者⾥⾯没有内容的时候,我们insert 是会失败的(底层数据库不允许插⼊⼀个空⾏),为了防⽌这种情况,我们要在这⾥指定⼀个列名,到时候如果发现将要插⼊的⾏为空⾏时,就会将你指定的这个列名的值设为null ,然后再向数据库中插⼊。(实际开发中⼀般设置为null 就好。)
⽐如:如果values 为空,最后⽣成的SQL ⼤概是"INSERT INTO table"这样的,那么这是⼀个错误的SQL ,肯定插⼊失败。但是如果指定了nullColumnHack ,最终会⽣成实际android 源码如下:
public void insertOrReplace(List<GroupMember> listMember) { SQLiteDatabase db = super .getDatabase (); db .beginTransaction (); for (int i = 0; i < listMember.size(); i++) { BaseUserInfo baseUserInfo = listMember .get (i).getBaseUserInfo (); ContentValues cv = new ContentValues(); cv .put ("user_id", baseUserInfo .getUserId ()); cv .put ("name", baseUserInfo .getName ()); cv .put ("logo", baseUserInfo .getLogo ()); // ⽣成的sql 是 INSERT INTRO OR REPLACE INTO 这样的 (如果存在就替换存在的字段值. 存在的判断标准是主键冲突, 这⾥的主键是userId). 下⾯会介绍int result = db .updateWithOnConflict (TABLE,cv,"user_id=?", new String[]{baseUserInfo .getUserId ()}) ; //如果有记录,则更新,并返回1,否则返回0 if(result<=0){ db .insertWithOnConflict (TABLE, null, cv, SQLiteDatabase .CONFLICT _REPLACE); } } db .setTransactionSuccessful (); db .endTransaction ();}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20insertWithOnConflict(String table, String nullColumnHack, ContentValues initialValues, intconflictAlgorithm)
1
2) conflictAlgorithm :
该参数是⼀个int 值,上⾯源码中也⽤到了(CONFLICT_VALUES[conflictAlgorithm]),那么CONFLICT_VALUES 的值是什么?Android 源码中如下:
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.size() > 0) ? 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++] = (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, String(), bindArgs); try { return uteInsert(); } finally { statement.close (); } } finally { releaseReference(); }}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39public static final int CONFLICT_ROLLBACK = 1;
public static final int CONFLICT_ABORT = 2;
public static final int CONFLICT_FAIL = 3;
public static final int CONFLICT_IGNORE = 4;
public static final int CONFLICT_REPLACE = 5;
public static final int CONFLICT_NONE = 0;
private static final String[] CONFLICT_VALUES = new String[]{"", " OR ROLLBACK ", " OR ABORT ", " OR FAIL ", " OR IGNORE ", " OR RE
>批量更新sql语句
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论