Iphone 从SQLite中删除和写入,使用JSON数据在MySQL中同步远程表
首先,我一直在阅读许多与我相似的问题,甚至从一些人那里得到一些建议,以达到我的目的,所以我感谢stackoverflow用户 好的,对于应用程序的iOS端,我总共有五个SQLite数据库表,对于远程服务器,它们在MySQL中是等价的。我在SQLite表中预加载的数据显示良好,应用程序按预期运行。当我从远程数据库下载JSON数据以替换iOS设备中存储的本地信息时,问题就出现了。我将通过引用一个表来保持简单:Iphone 从SQLite中删除和写入,使用JSON数据在MySQL中同步远程表,iphone,mysql,ios,json,sqlite,Iphone,Mysql,Ios,Json,Sqlite,首先,我一直在阅读许多与我相似的问题,甚至从一些人那里得到一些建议,以达到我的目的,所以我感谢stackoverflow用户 好的,对于应用程序的iOS端,我总共有五个SQLite数据库表,对于远程服务器,它们在MySQL中是等价的。我在SQLite表中预加载的数据显示良好,应用程序按预期运行。当我从远程数据库下载JSON数据以替换iOS设备中存储的本地信息时,问题就出现了。我将通过引用一个表来保持简单: // Create an object, reading its informat
// Create an object, reading its information from the local database.
Pregunta *objPregunta = [[Pregunta alloc] initWithPrimaryKey:0 database:delegate.database];
// Erase all data in the object's table (preguntas) see method below.
[objPregunta deleteAllFromDatabase];
// Obtain the remote objects retrieved via JSON, and cycle them.
NSArray *preguntas = (NSArray *)[responseDict objectForKey:@"preguntas"];
for (id pregunta in preguntas) {
// Create a dictionary storing the JSON object.
NSDictionary *pregunta_dict = (NSDictionary *) pregunta;
// Send the dictionary to the function for SQLite insertion.
[objPregunta insertNewRecordIntoDatabase:pregunta_dict];
}
// Free the object resources.
[objPregunta release];
这是与上述代码中Pregunta对象关联的SQLite删除函数:
- (void) deleteAllFromDatabase {
if(delete_statement == nil) {
const char *sql = "DELETE FROM preguntas";
if (sqlite3_prepare_v2(database, sql, -1, &delete_statement, NULL) != SQLITE_OK) {
NSAssert1(0, @"Error: Failed to prepare SQL statement: %s.", sqlite3_errmsg(database));
}
}
if (sqlite3_step(delete_statement) != SQLITE_DONE) {
NSAssert1(0, @"Failed to save priority with message: %s.", sqlite3_errmsg(database));
}
sqlite3_reset(delete_statement);
}
最后,这个函数使用传递给它的dictionary对象将新记录插入数据库:
- (void) insertNewRecordIntoDatabase:(NSDictionary *)pregunta_dict {
if (insert_statement == nil) {
const char *sql = "INSERT INTO preguntas (id_forma, numero, seccion, texto, respuesta, comentario, requiere_fotografia, fotografia, tipo) VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?)";
self.id_forma = [[pregunta_dict objectForKey:@"id_forma"] integerValue];
self.numero = [[pregunta_dict objectForKey:@"numero"] integerValue];
if([pregunta_dict objectForKey:@"seccion"] == [NSNull null]) {
self.seccion = nil;
} else {
self.seccion = [pregunta_dict objectForKey:@"seccion"];
}
self.texto = [pregunta_dict objectForKey:@"texto"];
if([pregunta_dict objectForKey:@"respuesta"] == [NSNull null]) {
self.respuesta = nil;
} else {
self.respuesta = [pregunta_dict objectForKey:@"respuesta"];
}
if([pregunta_dict objectForKey:@"comentario"] == [NSNull null]) {
self.comentario = nil;
} else {
self.comentario = [pregunta_dict objectForKey:@"comentario"];
}
self.requiere_fotografia = [pregunta_dict objectForKey:@"requiere_fotografia"];
if([pregunta_dict objectForKey:@"fotografia"] == [NSNull null]) {
self.fotografia = nil;
} else {
self.fotografia = [pregunta_dict objectForKey:@"fotografia"];
}
self.tipo = [pregunta_dict objectForKey:@"tipo"];
if (sqlite3_prepare_v2(database, sql, -1, &insert_statement, NULL) != SQLITE_OK) {
NSAssert1(0, @"Error: Failed to prepare SQL statement: %s.", sqlite3_errmsg(database));
} else {
@try {
sqlite3_bind_int (insert_statement, 1, self.id_forma);
sqlite3_bind_int (insert_statement, 2, self.numero);
sqlite3_bind_text(insert_statement, 3, [self.seccion UTF8String], -1, SQLITE_TRANSIENT);
sqlite3_bind_text(insert_statement, 4, [self.texto UTF8String], -1, SQLITE_TRANSIENT);
sqlite3_bind_text(insert_statement, 5, [self.respuesta UTF8String], -1, SQLITE_TRANSIENT);
sqlite3_bind_text(insert_statement, 6, [self.comentario UTF8String], -1, SQLITE_TRANSIENT);
sqlite3_bind_text(insert_statement, 7, [self.requiere_fotografia UTF8String], -1, SQLITE_TRANSIENT);
sqlite3_bind_text(insert_statement, 8, [self.fotografia UTF8String], -1, SQLITE_TRANSIENT);
sqlite3_bind_text(insert_statement, 9, [self.tipo UTF8String], -1, SQLITE_TRANSIENT);
}
@catch (NSException *exception) {
;
}
}
}
if (sqlite3_step(insert_statement) != SQLITE_DONE) {
NSAssert1(0, @"Failed to prepare SQL statement: %s.", sqlite3_errmsg(database));
} else {
NSLog(@"Pregunta insert_id: %lld", sqlite3_last_insert_rowid(database));
}
sqlite3_reset(insert_statement);
}
现在,代码的问题在于,它似乎插入的行不正确,因为当所有表的删除/插入过程完成,并且我从SQLite读取插入的数据时,我在数据库中的值会重复
我认为它与deleteAllFromDatabase
函数有关,但它似乎过于简单,不会引起任何麻烦。我还试图直接指定要为主键存储哪些值,但应用程序崩溃了,因为显然没有满足约束条件(我没有外键,每个表上只有一个主键)
你们有什么建议?请忽略空的catch块,我已经对它们进行了测试并删除了它们的代码,以便在我为您发布的源代码中缩短内容。此外,这些语句是类的局部静态变量,我可以根据需要重用和重置它们
感谢您提供的任何意见。为了更好地了解我在做什么,我将发回您可能需要我透露的任何进一步细节
以下是一些我已经设法抓住的发现:
- 由于我在TableView中显示行,所以我可以看到 数据库表中的值完全相同(I也相同) n记录它们),但主键(由自动生成)除外 SQLite整数自动增量)。。。所以这可能意味着 我的insert语句有问题,或者我发送 要插入的每一行的字典数据
- 就JSON资源中的数据而言,根本没有问题 使用它,我捕获了整个字符串,将其缩进并显示 它需要验证信息的完整性以及所有匹配项 远程MySQL表
- 在第一个代码块中,foreach循环读取:
但是在中,您会发现他们使用for(preguntas中的id pregunta){
(用*作为指针)。我尝试过将其设置为类似的,但我得到了一个错误,代码无论如何都不会编译for(id*item In items){
- 是否有可能需要以某种方式重置传递给
函数的insertNewRecordIntoDatabase:
,使其不包含以前的值?我假设每次迭代的数据都不同,但这证明我错了DSDictionary
- (可能执行插入的函数会被多次调用。)
- (我想你排除了这个可能性。)
Sascha我终于解决了这个问题。类的static
insert\u语句
变量(来自sqlite3\u stmt
)导致了这个问题,因为当我从类声明中删除它们并在-(void)insertNewRecordIntoDatabase:(NSDictionary*)中创建/完成它们时pregunta_dict
函数,然后所有插入都工作得很好。我现在在本地SQLite数据库中没有重复的行
因此,吸取的教训是:至少对于INSERT
语句,确保使用新的sqlite3\u stmt
对象和sqlite3\u finalize()
它们,而不是像我那样通过sqlite3\u reset()
循环使用它们,否则您可能会在后续调用中插入相同的数据
我还对整个类的insert函数做了一些更改,因为我现在将类的一个对象作为参数传递给它,并在插入时访问其属性以进行列匹配。下面是我的最终代码:
- (void) insertInstanceIntoDatabase: (Pregunta *)pregunta database: (sqlite3 *)db {
sqlite3_stmt *stmt_insert = nil;
const char *sql = "INSERT INTO preguntas (id_pregunta, id_forma, numero, seccion, texto, respuesta, comentario, requiere_fotografia, fotografia, tipo) VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
if (sqlite3_prepare_v2(db, sql, -1, &stmt_insert, NULL) != SQLITE_OK) {
NSAssert1(0, @"Error: Failed to prepare SQL statement: %s.", sqlite3_errmsg(db));
} else {
@try {
sqlite3_bind_int (stmt_insert, 1, pregunta.id_pregunta);
sqlite3_bind_int (stmt_insert, 2, pregunta.id_forma);
sqlite3_bind_int (stmt_insert, 3, pregunta.numero);
sqlite3_bind_text(stmt_insert, 4, [pregunta.seccion UTF8String], -1, SQLITE_TRANSIENT);
sqlite3_bind_text(stmt_insert, 5, [pregunta.texto UTF8String], -1, SQLITE_TRANSIENT);
sqlite3_bind_text(stmt_insert, 6, [pregunta.respuesta UTF8String], -1, SQLITE_TRANSIENT);
sqlite3_bind_text(stmt_insert, 7, [pregunta.comentario UTF8String], -1, SQLITE_TRANSIENT);
sqlite3_bind_text(stmt_insert, 8, [pregunta.requiere_fotografia UTF8String], -1, SQLITE_TRANSIENT);
sqlite3_bind_text(stmt_insert, 9, [pregunta.fotografia UTF8String], -1, SQLITE_TRANSIENT);
sqlite3_bind_text(stmt_insert,10, [pregunta.tipo UTF8String], -1, SQLITE_TRANSIENT);
}
@catch (NSException *exception) {
;
}
}
if (sqlite3_step(stmt_insert) != SQLITE_DONE) {
NSAssert1(0, @"Failed to prepare SQL statement: %s.", sqlite3_errmsg(db));
}
sqlite3_finalize(stmt_insert);
}
感谢您的反馈,Mundi,我更新了我的问题以反映进一步的发现。-也许主键可以帮助您。两个相同记录的主键是否相邻?表结构设置为自动添加主键,因为列是整数主键自动增量,我甚至不设置主键的列/value在插入新记录时…它们的插入由sqlite管理。