Android SQLite插入或更新

时间:2012-11-09 16:12:39

标签: android android-sqlite

从文档中可以看出,插入或更新的语法是:INSERT OR REPLACE INTO <table> (<columns>) VALUES (<values>),我的问题是有合并以下内容的函数吗?

public long insert (String table, String nullColumnHack, ContentValues values) 
public int update (String table, ContentValues values, String whereClause, String[] whereArgs)

还是必须使用准备好的SQL语句和rawQuery?

在Android中插入或更新的最佳做法是什么?

8 个答案:

答案 0 :(得分:81)

我相信您在一步中询问如何插入新行或更新现有行。虽然这可以在this answer中讨论的单个原始SQL中实现,但我发现使用SQLiteDatabase.insertWithOnConflict()使用CONFLICT_IGNORE for conflictAlgorithm在Android中分两步完成此操作更容易。

ContentValues initialValues = new ContentValues();
initialValues.put("_id", 1); // the execution is different if _id is 2
initialValues.put("columnA", "valueNEW");

int id = (int) yourdb.insertWithOnConflict("your_table", null, initialValues, SQLiteDatabase.CONFLICT_IGNORE);
if (id == -1) {
    yourdb.update("your_table", initialValues, "_id=?", new String[] {"1"});  // number 1 is the _id here, update to variable for your code
}

此示例假定表键为“_id”列设置,您知道记录_id,并且已经存在行#1(_id = 1,columnA =“valueA”,columnB =“valueB”) 。这是使用insertWithOnConflict与CONFLICT_REPLACE和CONFLICT_IGNORE

的区别
  • CONFLICT_REPLACE会将其他列中的现有值覆盖为null(即。columnB将变为NULL,结果将为_id = 1,columnA =“valueNEW”,columnB = NULL)。您丢失现有数据,我不会在我的代码中使用它。
  • CONFLICT_IGNORE将跳过现有行#1的SQL INSERT,您将在下一步中SQL更新此行,保留所有其他列的内容(即结果将为_id = 1,columnA =“valueNEW”, columnB =“valueB”)。

当您尝试插入尚未存在的新行#2时,代码将仅在第一个语句insertWithOnConflict中执行SQL INSERT(即结果将为_id = 2,columnA =“valueNEW”,columnB = NULL)。

小心this bug导致SQLiteDatabase.CONFLICT_IGNORE在API10(可能是API11)上出现故障。我在Android 2.2上测试时,查询返回0而不是-1。

如果您不知道记录键_id或者您的条件不会产生冲突,您可以将逻辑反转为UPDATE或INSERT 。这将在UPDATE期间保留记录键_id或在INSERT期间创建新记录_id。

int u = yourdb.update("yourtable", values, "anotherID=?", new String[]{"x"});
if (u == 0) {
    yourdb.insertWithOnConflict("yourtable", null, values, SQLiteDatabase.CONFLICT_REPLACE);
}

上面的示例假定您只想在记录中更新时间戳值,例如。如果先调用insertWithOnConflict,INSERT将根据时间戳条件的不同创建新的记录_id。

答案 1 :(得分:41)

这是您的方法SQLiteDatabase.insertWithOnConflict()。了解它在sqlite

上引用this document的含义

答案 2 :(得分:8)

SQLiteDatabase.replace()这样做,它基本上叫:

insertWithOnConflict(table, nullColumnHack, initialValues, CONFLICT_REPLACE);

太糟糕了,文档不是很清楚。

答案 3 :(得分:4)

您需要识别表格的列,使其成为一行。

实施例: _id,name,job,hours_worked

列是名称和作业,当您识别它时使用此方法:

private int getID(String name, String job){
    Cursor c = dbr.query(TABLE_NAME,new String[]{"_id"} "name =? AND job=?",new String[]{name,job},null,null,null,null);
    if (c.moveToFirst()) //if the row exist then return the id
        return c.getInt(c.getColumnIndex("_id"));
    return -1;
}

在你班上:

public void insertOrUpdate(String name, String job){
    ContentValues values = new ContentValues();
    values.put("NAME",name);
    values.put("JOB",job);

    int id = getID(name,job);
    if(id==-1)
        db.insert(TABLE_NAME, null, values);
    else
        db.update(TABLE_NAME, values, "_id=?", new String[]{Integer.toString(id)});
}

答案 4 :(得分:3)

SQLiteDatabase.replace()可能就是你要找的东西。我没有尝试过,但是文档说它返回了新插入的行的行ID ,所以它可能有效。

答案 5 :(得分:2)

我遇到了同样的问题,但我意识到当我的对象已经有一个ID它应该被更新,当它没有ID时它应该被插入所以这是我为解决问题所做的一步一步: / p>

1-你的对象getId使用Integer或初始化Id你认为合适的方式:这里是我的代码

public Integer getId() {
    return id;
}

2-在将所有内容放入ContentValues后,检查方法中的ID以进行插入或更新:

if(myObject.getId()!= null ){
        int count = db.update(TABLE_NAME,myContentValues,ID + " = ? ",
                new String[]{String.valueOf(myObject.getId())});
        if(count<=0){
            //inserting content values to db
            db.insert(TABLE_NAME, null, myContentValues);
        }
    } else {
        db.insert(TABLE_NAME, null, myContentValues);
    }

这里发生的是我检查Id是否存在我更新了那行但是如果update方法返回-1则表示没有带有该Id的行所以我插入了行,如果它没有Id我插入它。

希望这会有所帮助。

答案 6 :(得分:0)

怎么样? replaceOrThrow(String table,String nullColumnHack,ContentValues initialValues)

文档说...替换数据库中的行的便捷方法。 如果行尚不存在,则插入新行。

基本上它调用 insertWithOnConflict

答案 7 :(得分:0)

对我来说,如果您没有“ _id”(主键),那么所有方法都无效。

您应该先调用update,如果受影响的行为零,然后使用ignore将其插入:

blueback.wantsLayer = true
blueback.layer?.masksToBounds = true
blueback.layer?.cornerRadius = 50