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小时内删除。