关于SQLite的插入操作insert方法的理解
函数原型为:
long android.database.sqlite.SQLiteDatabase.insert(String table, String nullColumnHack, ContentValues values)
参数如下:
参数 | 意义 |
---|---|
String table | 要插入数据的表的名称 |
String nullColumnHack | 当values参数为空或者里面没有内容的时候,我们insert是会失败的(底层数据库不允许插入一个空行),为了防止这种情况,我们要在这里指定一个列名,到时候如果发现将要插入的行为空行时,就会将你指定的这个列名的值设为null,然后再向数据库中插入。 |
ContentValues values | 一个ContentValues对象,类似一个map.通过键值对的形式存储值。 |
理解: String nullColumnHack的作用是指定表中的一个字段名(列名),由于底层数据库不允许插入一个空行,因此,当values为空时,就会将我们指定的列的值设为null.
如下代码:
insert into tableName()values(); //这是错误的,不能为空
insert into tableName (nullColumnHack)values(null); //这是正确的
其实在底层,各种insert方法最后都会去调用insertWithOnConflict方法,这里我们粘贴出该方法的部分实现:
[java] view plaincopy/**
* General method for inserting a row into the database.
*
* @param table the table to insert the row into
* @param nullColumnHack SQL doesn't allow inserting a completely empty row,
* so if initialValues is empty this column will explicitly be
* assigned a NULL value
* @param initialValues this map contains the initial column values for the
* row. The keys should be the column names and the values the
* column values
* @param conflictAlgorithm for insert conflict resolver
* @return the row ID of the newly inserted row
* OR the primary key of the existing row if the input param 'conflictAlgorithm' =
* {@link #CONFLICT_IGNORE}
* OR -1 if any error
*/
public long insertWithOnConflict(String table, String nullColumnHack,
ContentValues initialValues, int conflictAlgorithm) {
if (!isOpen()) {
throw new IllegalStateException("database not open");
}
// Measurements show most sql lengths <= 152
StringBuilder sql = new StringBuilder(152);
sql.append("INSERT");
sql.append(CONFLICT_VALUES[conflictAlgorithm]);
sql.append(" INTO ");
sql.append(table);
// Measurements show most values lengths < 40
StringBuilder values = new StringBuilder(40);
Set<Map.Entry<String, Object>> entrySet = null;
if (initialValues != null && initialValues.size() > 0) {
entrySet = initialValues.valueSet();
Iterator<Map.Entry<String, Object>> entriesIter = entrySet.iterator();
sql.append('(');
boolean needSeparator = false;
while (entriesIter.hasNext()) {
if (needSeparator) {
sql.append(", ");
values.append(", ");
}
needSeparator = true;
Map.Entry<String, Object> entry = entriesIter.next();
sql.append(entry.getKey());
values.append('?');
}
sql.append(')');
} else {
sql.append("(" + nullColumnHack + ") ");
values.append("NULL");
}
这里我们可以看到,当我们的ContentValues类型的数据initialValues为null,或者size<=0时,就会在sql语句中添加nullColumnHack的设置。这里,如果我们不添加nullColumnHack的话,那么我们的sql语句最终的结果将会类似insert into tableName()values();这显然是不允许的。而如果我们添加上nullColumnHack,sql将会变成insert into tableName (nullColumnHack)values(null);这样是可以的。
最后:我们可以通过代码注释理解该方法的四个参数分别代表的意思和作用。
其中第四个参数解释:
* @param conflictAlgorithm for insert conflict resolver
* @return the row ID of the newly inserted row
* OR the primary key of the existing row if the input param 'conflictAlgorithm' =
* {@link #CONFLICT_IGNORE}
它表示如果插入操作有冲突,该如何处理,比如说新插入的数据的primary key与已有的一条数据primary key相同。