如果可能,在插入数据库时​​保留密钥

时间:2014-01-03 09:17:58

标签: android sqlite

我想写一个方法,如果可能的话,将从CSV保存主键将数据导入数据库。这意味着,如果该密钥在DB中不存在,它将插入具有相同密钥的记录,否则将使用新密钥插入记录。

为此,我写下了按计划工作的代码。但是,每次重复密钥时,我都会在LogCat中收到“PRIMARY KEY必须唯一(代码19)”的错误(这是可以理解的)。

所以,我的问题是:

  1. 还有更好的方法吗?
  2. 如果没有,有什么方法可以在logCat中抑制这些错误吗?
  3. 这些错误日志会导致任何性能问题,还是应该忽略它们?
  4. 我的代码:

    JSONArray jArray = new JSONArray(result); // whole JSON Array of data
    String[] data;
    int cnt;
    long flag=0;
    mylibmandbhandler db = new mylibmandbhandler(context); //db class
    int maxlength = jArray.length();
    for (int i = 0; i < maxlength; i++) {
        JSONObject json = jArray.getJSONObject(i);
        cnt = 0;
        dataline = new String[3];
        dataline[cnt++] = json.getString("bookid"); //PRIMARY KEY
        dataline[cnt++] = json.getString("bookname");
        dataline[cnt++] = json.getString("writer");
        flag = db.addRecord(new mylibman(dataline)); //ADDS RECORD USING db.insert(TABLE_NAME, null, values);
        if(flag==-1){
            dataline[0]="-1"; // IF PRIMARY KEY EXISTS MAKE BOOKID = -1, WHICH WILL IGNORE BOOKID IN db.addRecord METHOD
            db.addRecord(new mylibman(dataline));
        }
    }
    db.close();
    

    db.addRecord

    public long addRecord(mylibman mylibman) { //mylibman is custom class
        SQLiteDatabase db = this.getWritableDatabase();
        ContentValues values = new ContentValues();
        if(mylibman.getBookid() != -1){
            values.put(KEY_ID, mylibman.getBookid());
        }
        values.put(KEY_NAME, mylibman.getBookname());
        values.put(KEY_WRITER, mylibman.getWriter());
        // Inserting Row
        long numrow = db.insert(TABLE_NAME, null, values);
        db.close();
        return numrow;
    }
    

    logcat的:

    01-03 03:50:26.557: E/SQLiteDatabase(1509): android.database.sqlite.SQLiteConstraintException: PRIMARY KEY must be unique (code 19)
    01-03 03:50:26.557: E/SQLiteDatabase(1509):     at android.database.sqlite.SQLiteConnection.nativeExecuteForLastInsertedRowId(Native Method)
    01-03 03:50:26.557: E/SQLiteDatabase(1509):     at android.database.sqlite.SQLiteConnection.executeForLastInsertedRowId(SQLiteConnection.java:782)
    01-03 03:50:26.557: E/SQLiteDatabase(1509):     at android.database.sqlite.SQLiteSession.executeForLastInsertedRowId(SQLiteSession.java:788)
    01-03 03:50:26.557: E/SQLiteDatabase(1509):     at android.database.sqlite.SQLiteStatement.executeInsert(SQLiteStatement.java:86)
    01-03 03:50:26.557: E/SQLiteDatabase(1509):     at android.database.sqlite.SQLiteDatabase.insertWithOnConflict(SQLiteDatabase.java:1469)
    01-03 03:50:26.557: E/SQLiteDatabase(1509):     at android.database.sqlite.SQLiteDatabase.insert(SQLiteDatabase.java:1339)
    01-03 03:50:26.557: E/SQLiteDatabase(1509):     at com.migrationdesk.mylibman.mylibmandbhandler.addRecord(mylibmandbhandler.java:106)
    01-03 03:50:26.557: E/SQLiteDatabase(1509):     at com.migrationdesk.mylibman.MyImportServiceClass$RemoteConnectivity.doInBackground(MyImportServiceClass.java:281)
    01-03 03:50:26.557: E/SQLiteDatabase(1509):     at com.migrationdesk.mylibman.MyImportServiceClass$RemoteConnectivity.doInBackground(MyImportServiceClass.java:1)
    01-03 03:50:26.557: E/SQLiteDatabase(1509):     at android.os.AsyncTask$2.call(AsyncTask.java:288)
    01-03 03:50:26.557: E/SQLiteDatabase(1509):     at java.util.concurrent.FutureTask.run(FutureTask.java:237)
    01-03 03:50:26.557: E/SQLiteDatabase(1509):     at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:231)
    01-03 03:50:26.557: E/SQLiteDatabase(1509):     at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
    01-03 03:50:26.557: E/SQLiteDatabase(1509):     at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
    01-03 03:50:26.557: E/SQLiteDatabase(1509):     at java.lang.Thread.run(Thread.java:841)
    

2 个答案:

答案 0 :(得分:1)

  

我想写一个方法,如果可能的话,将从CSV保存主键将数据导入数据库。这意味着,如果该密钥在DB中不存在,它将插入具有相同密钥的记录,否则将使用新密钥插入记录。

我建议您创建新的主键并将旧键保留在另一个非唯一列中。我没有看到保留你真正不知道的id保存的好处,并且自动生成的id可能会产生进一步的冲突。

除此之外,对当前方法进行了一些改进:

  1. 请勿在{{1​​}}中打开和关闭数据库。相反,在addRecord()循环之外打开数据库并在其后关闭它,将引用传递给for方法。

  2. 在单个数据库事务中捆绑多个插入(假设为1000),而不是在单独的隐式事务中执行每个插入。这对减少I / O产生了巨大影响,从而提高了性能。

  3. 您获得的异常将冒泡到更高级别的catch块。由于循环不再运行,因此恢复逻辑将不起作用。相反,您可以指定SQL冲突解决策略(除了抛出),例如

    addRecord()

答案 1 :(得分:0)

因此检查该id是否存在,如果它确实创建了一个没有id的新插入,假设您的主键设置为autoincrement,它将为给定对象生成一个新id,或者如果id仍然是空闲的,只需插入它?

我错过了什么?

所以,获取一个列表,其中包含当前在db中的所有id,如果list包含当前id,则插入不带id,否则使用id插入。使它成为批次,性能应该没问题。