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);
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 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.
in my application I have stored the data in my sqlite3 database and uploading all my sqlite3 database to my online sever, once it copied to my server, I want to delete all my records I have stored in my local database.
I have two view controller first view controller, where I store the data to sqlite3 second view controller I have used to load the data to my server I have given like if user connected to network it has to upload the data.
I want like after uploading data to my server I want to delete all the records in my local database.
I have already tried some method its not working please tell me how to resolve this.
- (void) Delete_LoginData
{
if(sqlite3_open([self.filePath UTF8String], &db) == SQLITE_OK)
{
const char *sql = "DELETE * FROM reg";
sqlite3_stmt *statement;
if(sqlite3_prepare_v2(db, sql,-1, &statement, NULL) == SQLITE_OK)
{
sqlite3_reset(statement);
}
}
}
I called this function in my Reachability.
- (BOOL)reachable
{
Reachability *reach = [Reachability reachabilityWithHostName:#"www.google.com"];
NetworkStatus internetStatus = [reach currentReachabilityStatus];
if(internetStatus == NotReachable)
{
}
else
{
[self Delete_LoginData];
}
return YES;
}
My file path.
- (NSString *) filePath
{
NSArray *paths = filepath, YES);
return [[paths objectAtIndex:0] stringByAppendingPathComponent:#"bp.sqlite"];
}
Code open the db.
- (void)openDB
{
if (sqlite3_open([[self filePath] UTF8String], &db)!=SQLITE_OK)
{
sqlite3_close(db);
NSAssert(0, #"Database failed to open");
}
else
{
NSLog(#"database opened");
}
}
I have used this above method to delete record from my local database its not working please to where I'm doing wrong.
Thanks.
Use sqlite3_step instead of sqlite3_reset to execute the query
if(sqlite3_open([self.filePath UTF8String], &db) == SQLITE_OK)
{
const char *sql = "DELETE FROM reg";
sqlite3_stmt *statement;
if(sqlite3_prepare_v2(db, sql,-1, &statement, NULL) == SQLITE_OK)
{
if(sqlite3_step(statement) == SQLITE_DONE){
// executed
}else{
//NSLog(#"%s",sqlite3_errmsg(db))
}
}
sqlite3_finalize(statement);
}
sqlite3_close(db);
sqlite3_prepare_v2 doesn't act the execution You need to take a step into it
if(sqlite3_open([self.filePath UTF8String], &db) == SQLITE_OK){
NSString *sql = "DELETE FROM reg";
const char *query_st = [sql UTF8String];
if(sqlite3_prepare_v2(database, query_st, -1, &statement, NULL) == SQLITE_OK){
// Loop through the results and add them to the feeds array
if(sqlite3_step(statement) == SQLITE_DONE) {
// Deleted records,....
}else{
NSAssert1(0,#"Error when counting rows %s",sqlite3_errmsg(database));
}
sqlite3_finalize(statement);
}
sqlite3_close(database);
}
You can do like this,
sqlite3_stmt *statement;
- (void) Delete_LoginData
{
// Open database first
if(sqlite3_open([self.filePath UTF8String], &db) == SQLITE_OK)
{
// Sql query
const char *sql = "DELETE FROM reg";
// We are preparing the statement here
if(sqlite3_prepare_v2(db, sql,-1, &statement, NULL) == SQLITE_OK)
{
// If that prepared statement is OK then we can execute that statement
if(sqlite3_step(statement) == SQLITE_DONE)
{
NSLog(#" Records deleted successfully..");
}
else
{
NSLog(#" Opppsss..... Unable to delete records..");
}
}
// Finalizing the statement
sqlite3_finalize(statement);
// Closing the database
sqlite3_close(db);
}
Hope this work for you...
Thank you...
What am i doing wrong here?? i have three table in database, and i need to delete all data from them.
-(void)deleteAllDataFromTables
{
AppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
NSLog(#"%#", appDelegate.databasePath);
int result = sqlite3_open([appDelegate.databasePath UTF8String], &db);
if(result == SQLITE_OK)
{
NSLog(#"deleteCalled");
const char *deleteData = "delete from CustomerNumberTable";
int outcome = sqlite3_prepare_v2(db, deleteData, -1, &statement, NULL);
if(outcome == SQLITE_OK)
{
int res = sqlite3_step(statement);
if(res == SQLITE_DONE)
{
NSLog(#"deleted from Customer Table");
}
else
{
NSLog(#"not able to execute step statement");
}
}
else
{
NSLog(#"not deleted from Customer Table");
NSLog(#"the error is %s", sqlite3_errmsg(db));
}
sqlite3_finalize(statement);
const char *deleteData2 = "delete from KeyCodeTable";
int outcome2 = sqlite3_prepare_v2(db, deleteData2, -1, &statement, NULL);
if(outcome2 == SQLITE_OK)
{
int res = sqlite3_step(statement);
if(res == SQLITE_DONE)
{
NSLog(#"deleted from KeyCodeTable");
}
else
{
NSLog(#"not able to execute step statement");
}
}
else
{
NSLog(#"not deleted from KeyCodeTable");
NSLog(#"the error is %s", sqlite3_errmsg(db));
}
sqlite3_finalize(statement);
const char *deleteData3 = "delete from SRNumberTable";
int outcome3 = sqlite3_prepare_v2(db, deleteData3, -1, &statement, NULL);
if(outcome3 == SQLITE_OK)
{
int res = sqlite3_step(statement);
if(res == SQLITE_DONE)
{
NSLog(#"deleted from SRNumberTable");
}
else
{
NSLog(#"not able to execute step statement");
}
}
else
{
NSLog(#"not deleted from SRNumberTable");
NSLog(#"the error is %s", sqlite3_errmsg(db));
}
sqlite3_finalize(statement);
}
else
{
NSLog(#"Not able to open database for deleting");
}
}
On console, i am getting
Application[54974:a0b] deleteCalled
2014-01-03 16:12:55.442 Application[54974:a0b] deleted from Customer Table
2014-01-03 16:12:55.443 Application[54974:a0b] deleted from KeyCodeTable
2014-01-03 16:12:55.445 Application[54974:a0b] deleted from SRNumberTable
But when i am opening the database in on mac, the data is intact there..!! What is wrong with my code?? why isn't the data getting deleted??
I think you are copying your database from bundle to documents directory. So, the updated database will be present in documents directory. You seems to look the database from your workspace which is never going to be of updated one.
Your code opens database with sqlite3_open(), but does not close it using sqlite3_close(). This means that your database is probably still in open transaction, and quite possibly has 2 files: one is main database.db, and journal file database.db-journal which contains uncommitted intent to delete your tables.
You should make sure that your application closes database before you copy database file from the device to the host. At the very least, copy both main database AND journal file as one set. It is still likely to have consistency issues, but you should see your changes.
Try instead of sqlite3_prepare_v2 to sqlite3_exec. This working fine for me.
Just Ref:
char *errMsg;
const char *dbPath = [databasePath UTF8String];
if (sqlite3_open(dbPath, &database) == SQLITE_OK) {
NSLog(#"Db OPened ");
NSString *queryLists = [NSString stringWithFormat:#"delete from Table_name"];
const char *query_stmt = [queryLists UTF8String];
if (sqlite3_exec(database, query_stmt, NULL, NULL, &errMsg)
!= SQLITE_OK){
NSLog(#"Error %s", errMsg);
NSLog(#"Table Not Deleted");
}
}
1st thing Don't write same functionality code repeatedly in place create one function that delete all data from given table name,
2nd make sure you are looking at correct sqlite file in mac.
look this,
-(void)deleteAllData
{
[self deleteTable: CustomerNumberTable];
[self deleteTable: SRNumberTable];
[self deleteTable: KeyCodeTable];
}
-(void)deleteTable:(NSString *)table;
{
const char *dbpath=[appDelegate.databasePath UTF8String];
if (sqlite3_open(dbpath, &dtdb)==SQLITE_OK)
{
sqlite3_stmt *stmt;
const char *qry=[[NSString stringWithFormat:#"delete from %#",table] UTF8String];
sqlite3_prepare_v2(dtdb, qry, -1, &stmt, NULL);
if (sqlite3_step(stmt)==SQLITE_DONE)
{
NSLog(#"%# Table data deleted",table);
}
sqlite3_finalize(stmt);
sqlite3_close(dtdb);
}
}
I am trying to update one of my table's column upon button click.
The issue is that code isn't giving any exception still it is not updating the table.
When the view controller load again , it shows the old value rather then updated one.
Code for update db is attached below.
#try {
if(sqlite3_open([databasePath UTF8String], &database) == SQLITE_OK) {
NSString *sqlStatement = #"UPDATE messagesTable SET Favorite = 1 where MessageID=";
sqlStatement = [sqlStatement stringByAppendingString:msgId];
NSLog(#"sql statement: %#", sqlStatement);
const char *sql = [sqlStatement UTF8String];
int result = sqlite3_prepare_v2(database, sql, -1, &compiledStatement, NULL);
if(result != SQLITE_OK) {
NSLog(#"Prepare-error #%i: %s", result, sqlite3_errmsg(database));
}
// Release the compiled statement from memory
sqlite3_finalize(compiledStatement);
}
sqlite3_close(database);
}
#catch (NSException *exception) {
NSLog(#"Name: %#",exception.name);
NSLog(#"Reason: %#",exception.reason);
}
#finally {
}
Any suggestions are welcome. :-)
You are not calling sqlite3_step, which performs the update. After the sqlite3_prepare and before the sqlite3_finalize, you need something like:
if (sqlite3_step(compiledStatement) != SQLITE_DONE)
NSLog(#"%s: step error: %s", __FUNCTION__, sqlite3_errmsg(database));