I am trying to update row in a loop and its not working. I have explained the scenario below
I have got set of values from web services stored in arrays. Now i have to update those values in DB by looping through the array. Below is the code am using:
NSString *dbPath = [[NSBundle mainBundle] pathForResource:#"db_name" ofType:#"sqlite"];
sqlite3 *database;
sqlite3 *database1;
sqlite3_open([dbPath UTF8String], &database1);
sqlite3_open([dbPath UTF8String], &database);
NSInteger loopCnt = 0;
NSString *s = [[NSString alloc] init];
const char *sql;
sqlite3_stmt *selectstmt;
NSString *q = [[NSString alloc] init];
for(NSString *itemId in itemIds)
{
s = [NSString stringWithFormat:#"SELECT * from table where id=%#", itemId];
sql = [s UTF8String];
int result = sqlite3_prepare_v2(database, sql, -1, &selectstmt, NULL);
if(result == SQLITE_OK)
{
while(sqlite3_step(selectstmt) == SQLITE_ROW)
{
if ((char *)sqlite3_column_text(selectstmt, 0) != NULL)
{
rowNumVal = [NSString stringWithUTF8String:(char *)sqlite3_column_text(selectstmt, 0)];
col1 = [values1 objectAtIndex:loopCnt];
col2 = [values2 objectAtIndex:loopCnt];
if([rowNumVal integerValue] > 0)
{
q = [NSString stringWithFormat:#"UPDATE table set col1=?, col2=? WHERE id=?"];
}
}
}
}
sqlite3_finalize(selectstmt);
sqlite3_exec(database1, "BEGIN EXCLUSIVE TRANSACTION", 0, 0, 0);
sqlite3_stmt *stmt;
const char *query = [q UTF8String];
if(sqlite3_prepare_v2(database1, query, -1, &stmt, NULL)== SQLITE_OK)
{
if(sqlite3_bind_text(stmt, 1, [col1 UTF8String], -1, SQLITE_TRANSIENT) != SQLITE_OK)
{
NSLog(#"Error while binding column 1 %s", sqlite3_errmsg(database1));
}
if(sqlite3_bind_text(stmt, 2, [col2 UTF8String], -1, SQLITE_TRANSIENT) != SQLITE_OK)
{
NSLog(#"Error while binding column 2 %s", sqlite3_errmsg(database1));
}
if (sqlite3_step(stmt) != SQLITE_DONE){
NSLog(#"Delete commit failed. Error %s", sqlite3_errmsg(database1));
}
if(sqlite3_reset(stmt)!= SQLITE_OK){
NSLog(#"SQL error %s", sqlite3_errmsg(database1));
}
}
sqlite3_trace(database1, sqliteCallbackFunc, NULL);
sqlite3_finalize(stmt);
if(sqlite3_exec(database1, "COMMIT TRANSACTION", 0, 0, 0) != SQLITE_OK){
NSLog(#"SQL error %s", sqlite3_errmsg(database1));
}
loopCnt++;
}
sqlite3_close(database);
sqlite3_close(database1);
I am fetching the values using id to check row exists and if exists am updating. Everything logs and runs fine but still DB is not getting updated.
Please let me know where is the issue.
You need to call:
sqlite3_finalize(stmt);
Before:
if(sqlite3_reset(stmt)!= SQLITE_OK)
{
NSLog(#"SQL error %s", sqlite3_errmsg(database1));
}
In current code, you are resetting the prepared SQLite statement to it's initial state before finalizing it.
Another issue is, you are trying to update the database that is located in App Bundle. It won't work, because app bundle is read-only. You need to copy the database to document directory and do the operations on that copied database.
Related
I am selecting data from sqlite database. Problem is that using following code it works some time. But lets say we call this method for any other table twice then it shows null select statement for other method. Is any thing wrong in method so that if we use same for other tables some time it works some time not.
-(void)getAssessmentNumber:(NSString *)dbPath{
appDelegate=[[UIApplication sharedApplication]delegate];
NSString*fileDBPath=[[NSBundle mainBundle] pathForResource:#"Database" ofType:#"sqlite"];
if (sqlite3_open([fileDBPath UTF8String], &database) == SQLITE_OK)
{
// NSLog(#"%#",[self getDBPath]);
NSString *querySQL = [NSString stringWithFormat:#"Select Am.AssessmentID , Am.AssessmentName From AssessmentMaster Am LEFT JOIN AssessmentDepartmentMapping M ON M.AssessmentID = Am.AssessmentID LEFT JOIN DepartmentListing d ON d.departmentID =M.departmentID where d.departmentID = '%#'",appDelegate.departmentID];
NSLog(#"%#",querySQL);
const char *sql = [querySQL UTF8String];
sqlite3_stmt *selectstmt;
NSError *error;
[appDelegate.assessmentNumberArray removeAllObjects];
if (sqlite3_prepare_v2(database, sql, -1, &selectstmt, NULL) == SQLITE_OK)
{
while (sqlite3_step(selectstmt) == SQLITE_ROW)
{
NSInteger primaryKey = sqlite3_column_int(selectstmt, 0);
AssessmentListening *asmObj = [[AssessmentListening alloc] initWithPrimaryKey:primaryKey];
asmObj.assessmentID=[NSString stringWithFormat:#"%d",primaryKey];
asmObj.assessmentName = [NSString stringWithUTF8String:(char *)sqlite3_column_text(selectstmt, 1)];
[appDelegate.assessmentNumberArray addObject:asmObj];
}
}
else {
NSAssert1(0, #"Failed to create writable database file with message '%#'.", [error localizedDescription]);
}
// sqlite3_finalize(selectstmt);
}
sqlite3_close(database);
}
Is this fine for getting the data from table?
Your code needs a little cleanup.
- (void)getAssessmentNumber:(NSString *)dbPath {
NSString *fileDBPath = [[NSBundle mainBundle] pathForResource:#"Database" ofType:#"sqlite"];
if (sqlite3_open([fileDBPath UTF8String], &database) == SQLITE_OK) {
appDelegate = [[UIApplication sharedApplication] delegate];
[appDelegate.assessmentNumberArray removeAllObjects];
const char *sql = "Select Am.AssessmentID, Am.AssessmentName From AssessmentMaster Am LEFT JOIN AssessmentDepartmentMapping M ON M.AssessmentID = Am.AssessmentID LEFT JOIN DepartmentListing d ON d.departmentID = M.departmentID where d.departmentID = ?";
sqlite3_stmt *selectstmt;
if (sqlite3_prepare_v2(database, sql, -1, &selectstmt, NULL) == SQLITE_OK) {
sqlite3_bind_text(selectstmt, 0, [appDelegate.departmentID UTF8String], -1, SQLITE_TRANSIENT);
while (sqlite3_step(selectstmt) == SQLITE_ROW) {
NSInteger primaryKey = sqlite3_column_int(selectstmt, 0);
AssessmentListening *asmObj = [[AssessmentListening alloc] initWithPrimaryKey:primaryKey];
asmObj.assessmentID = [NSString stringWithFormat:#"%d", primaryKey];
asmObj.assessmentName = [NSString stringWithUTF8String:(char *)sqlite3_column_text(selectstmt, 1)];
[appDelegate.assessmentNumberArray addObject:asmObj];
}
sqlite3_finalize(selectstmt);
} else {
NSLog(#"Unable to prepare statement: %s", sqlite3_errmsg(database));
}
sqlite3_close(database);
} else {
NSLog(#"Unable to open the database from %#: %s", fileDBPath, sqlite3_errmsg(database);
}
}
Note all of the changes:
Only close the database if it is opened.
Only finalize the statement if it is prepared.
Don't build queries with stringWithFormat. Use the proper sqlite3_bind_xxx function to bind the values to the query. This ensures special characters are escaped and properly deals with quoting.
Use proper error checking. Use sqlite3_errmsg to get the error.
i am getting error in the sqlite updation,here the query is correctly given, but the value is not updating.here i need to update the description value Where the given place, Below i add my code please help me
-(void) update:(NSString *)filePath withName:(NSString *)place description:(NSString*)description
{
sqlite3* db = NULL;
int rc=0;
sqlite3_stmt* stmt =NULL;
rc = sqlite3_open_v2([filePath cStringUsingEncoding:NSUTF8StringEncoding], &db, SQLITE_OPEN_READWRITE , NULL);
if (SQLITE_OK != rc)
{
sqlite3_close(db);
NSLog(#"Failed to open db connection");
}
else
{
NSString * query = [NSString stringWithFormat:#"UPDATE places SET description=%# WHERE place=%#",description,place];
sqlite3_bind_text(stmt, 1, [place UTF8String], -1, SQLITE_TRANSIENT);
sqlite3_bind_text(stmt, 2, [description UTF8String], -1, SQLITE_TRANSIENT);
NSLog(#"query %#",query);
char * errMsg;
rc = sqlite3_exec(db, [query UTF8String] ,NULL,&stmt,&errMsg);
if(SQLITE_OK != rc)
{
NSLog(#"Failed to insert record rc:%d, msg=%s",rc,errMsg);
}
else{
NSLog(#"Sucessfully updated");
}
sqlite3_finalize(stmt);
sqlite3_close(db);
}
}
Table Creation
-(int) createTable:(NSString*) filePath
{
sqlite3* db = NULL;
int rc=0;
NSLog(#"create");
rc = sqlite3_open_v2([filePath cStringUsingEncoding:NSUTF8StringEncoding], &db, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, NULL);
if (SQLITE_OK != rc)
{
sqlite3_close(db);
NSLog(#"Failed to open db connection");
}
else
{
char * query ="CREATE TABLE IF NOT EXISTS places ( id INTEGER PRIMARY KEY AUTOINCREMENT,place TEXT ,locationname TEXT,time TEXT,description TEXT,notifyTime TEXT,radius TEXT,lat DOUBLE,lon DOUBLE ,notify TEXT,selection INTEGER)";
char * errMsg;
rc = sqlite3_exec(db, query,NULL,NULL,&errMsg);
if(SQLITE_OK != rc)
{
NSLog(#"Failed to create table rc:%d, msg=%s",rc,errMsg);
}
else{
NSLog(#"Sucessfully Created ");
}
sqlite3_close(db);
}
return rc;
}
First open the DB connection.
Then write below code.
NSString * query = [NSString stringWithFormat:#"UPDATE places SET description=%# WHERE place=%#",description,place];
SQL=[NSString stringWithString:query];
sqlite3_stmt *insert_statement=nil;
if (sqlite3_prepare_v2(database, [SQL UTF8String], -1, &insert_statement, NULL) != SQLITE_OK) {
//NSAssert1(0, #"Error: failed to prepare statement with message '%s'.", sqlite3_errmsg(database));
NSLog(#"Error: failed to prepare statement with message '%s'.", sqlite3_errmsg(database));
}
int result=sqlite3_step(insert_statement);
sqlite3_finalize(insert_statement);
and then close the DB connection
try this ...check db is whether it is opened or not and change this code...
-(void) update:(NSString *)filePath withName:(NSString *)place description:(NSString*)description
{
sqlite3* db = NULL;
int rc=0;
sqlite3_stmt* stmt =NULL;
rc = sqlite3_open_v2([filePath cStringUsingEncoding:NSUTF8StringEncoding], &db, SQLITE_OPEN_READWRITE , NULL);
if (SQLITE_OK != rc)
{
sqlite3_close(db);
NSLog(#"Failed to open db connection");
}
else
{
/*
NSString *strMQueryupdate=[NSString stringWithFormat:#"update br set TOTAL='%#',QUTY='%#' WHERE PID='%#'",[#(total )stringValue],[#(lblQtn )stringValue],produdId];
*/
NSString * query = [NSString stringWithFormat:#"UPDATE places SET description='%#' WHERE place='%#'",description,place];
const char *sql = [query UTF8String];
if (sqlite3_prepare_v2(db, sql, -1, & stmt, NULL) != SQLITE_OK)
{
NSLog(#"update fails");
}
else
{
sqlite3_bind_text(stmt, 1, [place UTF8String], -1, SQLITE_TRANSIENT);
sqlite3_bind_text(stmt, 2, [description UTF8String], -1, SQLITE_TRANSIENT);
int success = sqlite3_step(stmt);
sqlite3_reset(stmt);
if (success == SQLITE_ERROR)
{
}
else
{
NSLog(#"update success");
}
sqlite3_finalize(update_statement);
sqlite3_close(db);
}
}
You're using prepared statements incorrectly. You hard-code the values in a string (a bad idea) and then setting the placeholder values -- which makes no sense as there are no placeholders in your SQL. Try something like:
NSString * query = #"UPDATE places SET description= ? WHERE place= ?";
sqlite3_bind_text(stmt, 1, [place UTF8String], -1, SQLITE_TRANSIENT);
sqlite3_bind_text(stmt, 2, [description UTF8String], -1, SQLITE_TRANSIENT);
The reason you don't want to include the values directly in the query string: imagine someone passing in a value for place like "London'; drop table places;". (Not sure if that'll work but it should give you some idea of the kind of mischief that a user could get up to.)
I have sqlite database in iPhone app and there I store questions.
I get one question, user answers YES or NO, result is showing on second viewController and when second viewController is closing I get another question.
Everything works perfectly and suddenly after 30-40 questions, program cannot open database.
if(sqlite3_open([DBPath UTF8String], &database) == SQLITE_OK) - it fails.
Any answers?
This function:
// get Question from Database
- (void)getQuestion:(int)getQ
{
NSLog(#"getQuestion Started");
sqlite3 *database;
sqlite3_stmt *compiledStatement = NULL;
if(sqlite3_open([DBPath UTF8String], &database) == SQLITE_OK)
{
NSLog(#"sqlite opened");
const char *sql = "Select QuestionID, Question from cQuestions WHERE ExerciseLinID = ? ORDER BY QuestionID LIMIT ?, 1";
if(sqlite3_prepare_v2(database, sql, -1, &compiledStatement, NULL) != SQLITE_OK)
NSAssert1(0, #"Error while creating detail view statement. '%s'", sqlite3_errmsg(database));
int curExID = [[listOfExID objectAtIndex:ExSel] integerValue];
sqlite3_bind_int(compiledStatement, 1, curExID);
sqlite3_bind_int(compiledStatement, 2, getQ);
if(SQLITE_DONE != sqlite3_step(compiledStatement))
{
NSLog(#"Got one record");
selectedQues = sqlite3_column_int(compiledStatement, 0);
NSLog(#"selectedQues = %i", selectedQues);
const char *QuNam = (char *)sqlite3_column_text(compiledStatement, 1);
if(QuNam == nil)
NSLog(#"!!! No data found.");
else
{
if( iWhat == YES )
_labQuestion.text = [[NSString alloc] initWithCString:QuNam encoding:NSASCIIStringEncoding];
else
_labQuestionPad.text = [[NSString alloc] initWithCString:QuNam encoding:NSASCIIStringEncoding];
}
}
}
else
{
NSLog(#"!!! Open error. %s", sqlite3_errmsg(database));
NSLog(#"!!! Open error. %d", sqlite3_errcode(database));
}
sqlite3_close(database);
}
Add some NSLog to understand which is the error.
if(sqlite3_open([DBPath UTF8String], &database) == SQLITE_OK) {
// Your Code
}
else {
NSLog(#"sqlite3_open failed. Error:%d. %s", sqlite3_errcode(database), sqlite3_errmsg(database));
}
One potential problem is the fact that you aren't closing your database, are you closing it?
sqlite3_close(database);
I have done lot of googling on updating the created sqlite table still i did not able to update my table in my sample app .Can any one please tell me what is wrong with my below code .IT works fine till sqlite3_prepare_v2.Once it reach if(sqlite3_prepare_v2(database, sql, -1, &statement, NULL)==SQLITE_OK) condition it is not going into this if() condition can any one tell what is happening here?
const char *dbpath = [[self DBPath] UTF8String];
if(sqlite3_open(dbpath, &database) == SQLITE_OK)
{
NSString *querySql=[NSString stringWithFormat:#"UPDATE Table1 SET AppEndTime = %# WHERE AppID= %d",AppEndTime,appID];
const char *sql=[querySql UTF8String];
if(sqlite3_prepare_v2(database, sql, -1, &statement, NULL)==SQLITE_OK){
sqlite3_bind_int(statement, 1, sessionID);
sqlite3_bind_text(statement, 6, [sessionEndTime UTF8String], -1, SQLITE_TRANSIENT);
}
}
char* errmsg;
sqlite3_exec(database, "COMMIT", NULL, NULL, &errmsg);
if(SQLITE_DONE != sqlite3_step(statement)){
NSLog(#"Error while updating. %s", sqlite3_errmsg(database));
}
else{
sqlite3_reset(statement);
}
sqlite3_finalize(statement);
sqlite3_close(database);
Please replace you code as given below.I hope it will solve your problem.
if (sqlite3_prepare_v2(database, sql, -1, &Statement1, NULL) == SQLITE_OK) {
sqlite3_bind_text(Statement1, 1, [status UTF8String], -1, SQLITE_TRANSIENT);
sqlite3_bind_text(Statement1, 2, [messageID UTF8String], -1, NULL);
int success = sqlite3_step(Statement1);
if(success != SQLITE_ERROR)
{
// NSLog(#"Success");
}
sqlite3_finalize(Statement1);
}
Here is my code which update created table. Have a look hope it'll help you.
-(BOOL)updateMyTable{
BOOL isGood = YES;
#try {
NSString *fName = [user_dic valueForKey:#"fName"];
NSString *lName = [user_dic valueForKey:#"lName"];
NSString *email_id = [user_dic valueForKey:#"email_id"];
NSString *employee_id = [user_dic valueForKey:#"employee_id"];
fName= [fName stringByReplacingOccurrencesOfString:#"'" withString:#"''"];
lName= [lName stringByReplacingOccurrencesOfString:#"'" withString:#"''"];
email_id= [email_id stringByReplacingOccurrencesOfString:#"'" withString:#"''"];
employee_id= [employee_id stringByReplacingOccurrencesOfString:#"'" withString:#"''"];
// NSString *autoId = [user_dic valueForKey:#"autoId"];
NSString *sql = [NSString stringWithFormat:#"UPDATE tbl_profile SET fName = '%#', lName = '%#', email_id = '%#' ,employee_id = '%#' WHERE autoId = '%#'",fName,lName,email_id,employee_id,autoId];
[database executeUpdate:sql,nil];
if (MyDelegate.isLogging) {
NSLog(#"edit user QUERY---- >>>>%#",sql);
NSLog(#"edit user RESULT CODE ---- >>>>%d:", [database lastErrorCode]);
NSLog(#"edit user RESULT ERROR MESSAGE ---- >>>>%#",[database lastErrorMessage]);
}
}#catch (NSException *exception) {
isGood = NO;
}
#finally {
}
return isGood;
Please make sure your Sqlite file is in the documents directory,Not in project folder.
Update and insert will work if and only if the file is in the document directory
see this answer
I am trying to update my sqlite database but this code is not working for me.
Please help me to find what is wrong with this.
-(BOOL)StoreFavourite:(NSString*)fav :(int)DuaId
{
NSString* mydbpath=[self pathfinder];
const char *dbpath=[mydbpath UTF8String];
if(sqlite3_open(dbpath,&database )==SQLITE_OK)
{
NSString *query = [NSString stringWithFormat:#"UPDATE Dua SET
favourite=\'%#\' WHERE dua_id=%d ",fav,DuaId];
const char *query_statement=[query UTF8String];
if(sqlite3_prepare_v2(database, query_statement, -1, &statement, NULL)==SQLITE_OK)
{
while(sqlite3_step(statement) == SQLITE_DONE)
{
return YES;
}
sqlite3_finalize(statement);
}
}
return YES;
}
Please check your "mydbpath" by putting NSLog.I think you have given incorrect path.
Also try to use:
NSString *query = [NSString stringWithFormat:#"UPDATE Dua SET favourite='%#' WHERE dua_id=%d ",fav,DuaId];
here are some reason for due to which the sqlite3_prepare_v2 != SQLITE_OK :
1.The table may not present into the database.
2.Wrong query statement .
3.Wrong column name into the query statement.
You can find the exact problem using error statement by putting following in else:
NSAssert1(0, #"Error while inserting data. '%s'", sqlite3_errmsg(database))
please try in following manner
-(BOOL)StoreFavourite:(NSString*)fav :(int)DuaId
{
sqlite3_stmt *statement=nil;
NSString *mydbpath=[self pathfinder];
NSString *query;
if(sqlite3_open([mydbpath UTF8String],&database) == SQLITE_OK)
{
query = [NSString stringWithFormat: #"update Dua set favourite=? where dua_id=?"];
if(sqlite3_prepare_v2(database, [query UTF8String], -1, &statement, NULL)
== SQLITE_OK)
{
sqlite3_bind_int(statement, 2, DuaId);
sqlite3_bind_text(statement, 1, [fav UTF8String], -1, SQLITE_TRANSIENT);
if(sqlite3_step(statement))
{
return YES;
}
else
{
return NO;
}
}
sqlite3_finalize(statement);
}
sqlite3_close(database);
return NO;
}