我想写一个方法,如果可能的话,将从CSV保存主键将数据导入数据库。这意味着,如果该密钥在DB中不存在,它将插入具有相同密钥的记录,否则将使用新密钥插入记录。
为此,我写下了按计划工作的代码。但是,每次重复密钥时,我都会在LogCat中收到“PRIMARY KEY必须唯一(代码19)”的错误(这是可以理解的)。
所以,我的问题是:
我的代码:
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)
答案 0 :(得分:1)
我想写一个方法,如果可能的话,将从CSV保存主键将数据导入数据库。这意味着,如果该密钥在DB中不存在,它将插入具有相同密钥的记录,否则将使用新密钥插入记录。
我建议您创建新的主键并将旧键保留在另一个非唯一列中。我没有看到保留你真正不知道的id保存的好处,并且自动生成的id可能会产生进一步的冲突。
除此之外,对当前方法进行了一些改进:
请勿在{{1}}中打开和关闭数据库。相反,在addRecord()
循环之外打开数据库并在其后关闭它,将引用传递给for
方法。
在单个数据库事务中捆绑多个插入(假设为1000),而不是在单独的隐式事务中执行每个插入。这对减少I / O产生了巨大影响,从而提高了性能。
您获得的异常将冒泡到更高级别的catch块。由于循环不再运行,因此恢复逻辑将不起作用。相反,您可以指定SQL冲突解决策略(除了抛出),例如
addRecord()
答案 1 :(得分:0)
因此检查该id是否存在,如果它确实创建了一个没有id的新插入,假设您的主键设置为autoincrement,它将为给定对象生成一个新id,或者如果id仍然是空闲的,只需插入它?
我错过了什么?
所以,获取一个列表,其中包含当前在db中的所有id,如果list包含当前id,则插入不带id,否则使用id插入。使它成为批次,性能应该没问题。