if (sqlite3_step(statement) == SQLITE_DONE) loop does not execute - iOS - ios

below is my code to update records in database...
-(BOOL) addScoreInDatabase:(classname *)objGames
{
BOOL success;
sqlite3 *database;
const char *dbpath = [self.databasePath UTF8String];
if(sqlite3_open(dbpath, &database) == SQLITE_OK)
{
sqlite3_stmt *statement;
NSData *strJson = [objGames getJSON];
NSString *strContent = [[[[NSString alloc]
initWithData:strJson encoding:NSUTF8StringEncoding] stringByReplacingOccurrencesOfString:#"\\" withString:#""]stringByReplacingOccurrencesOfString:#"null" withString:#"\"\""];
NSLog(#"strcom %#",strContent);
NSString *query = [NSString stringWithFormat:#"UPDATE gamescore SET data ='%#' WHERE id = 1",strContent];
NSLog(#"query %#",query);
const char *sqlStatement = [query UTF8String];
if(sqlite3_prepare_v2(database, sqlStatement, -1, & statement, NULL) == SQLITE_OK)
{
if (sqlite3_step(statement) == SQLITE_DONE)
{
success = TRUE;
}
else
{
success = FALSE;
}
sqlite3_exec(database, "VACUUM;", 0, 0, nil);
}
sqlite3_finalize(statement);
sqlite3_close(database);
}
return success;
}
and it doesn't go inside if (sqlite3_step(statement) == SQLITE_DONE) loop
and Resulted query is
UPDATE gamescore SET data ='{
"title" : "pacman",
"time" : "55",
"score" : "200",
"level" : "1"
}' WHERE id = 1
and when i execute this query in Sqlite Manager it doesn't update the records instead it shows something like this
Can anybody help me to update my records ?!..Thanks !!

You can use sqlite3_exec() method instead of sqlite3_step().
sqlite3_exec() will execute whatever the query you have given.
Try this out.
enter code
-(BOOL) addScoreInDatabase:(classname *)objGames
{
BOOL success;
sqlite3 *database;
const char *dbpath = [self.databasePath UTF8String];
if(sqlite3_open(dbpath, &database) == SQLITE_OK)
{
sqlite3_stmt *statement;
NSData *strJson = [objGames getJSON];
NSString *strContent = [[[[NSString alloc]
initWithData:strJson encoding:NSUTF8StringEncoding] stringByReplacingOccurrencesOfString:#"\\" withString:#""]stringByReplacingOccurrencesOfString:#"null" withString:#"\"\""];
NSLog(#"strcom %#",strContent);
NSString *query = [NSString stringWithFormat:#"UPDATE gamescore SET data ='%#' WHERE id = 1",strContent];
NSLog(#"query %#",query);
const char *sqlStatement = [query UTF8String];
if(sqlite3_prepare_v2(database, sqlStatement, -1, & statement, NULL) == SQLITE_OK)
{
sqlite3_exec(database, "VACUUM;", 0, 0, nil);
}
sqlite3_finalize(statement);
sqlite3_close(database);
}
return success;
}

Related

Getting database locked error while adding row 2nd time [duplicate]

This question already has answers here:
sqlite error database is locked
(8 answers)
Closed 6 years ago.
I am getting error Database Locked.
at first attempt it adds the row but after that i am getting the error
database locked.
I am trying to make web page saver so at first time when app loads it is adding the row but when again I try to save any webpage it is not saving and I am getting the error database locked.
Even the deletion is also not happening after saving one web page.
#import "DBManager.h"
static DBManager *sharedInstance = nil;
static sqlite3 *database = nil;
static sqlite3_stmt *statement = nil;
#implementation DBManager
+(DBManager*)getSharedInstance{
if (!sharedInstance) {
sharedInstance = [[super allocWithZone:NULL]init];
[sharedInstance createDB];
}
return sharedInstance;
}
-(BOOL)createDB{
NSString *docsDir;
NSArray *dirPaths;
// Get the documents directory
dirPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
docsDir = dirPaths[0];
// Build the path to the database file
databasePath = [[NSString alloc] initWithString:[docsDir stringByAppendingPathComponent: #"browser.db"]];
BOOL isSuccess = YES;
NSFileManager *filemgr = [NSFileManager defaultManager];
if ([filemgr fileExistsAtPath: databasePath ] == NO)
{
const char *dbpath = [databasePath UTF8String];
if (sqlite3_open(dbpath, &database) == SQLITE_OK)
{
char *errMsg;
NSLog(#"insod");
const char *sql_stmt ="create table if not exists list(sno int primary key,name varchar(50),category varchar(30),path varchar(500),fav int)";
if (sqlite3_exec(database, sql_stmt, NULL, NULL, &errMsg)
!= SQLITE_OK)
{
isSuccess = NO;
NSLog(#"Failed to create table");
}
sqlite3_close(database);
return isSuccess;
}
else {
isSuccess = NO;
NSLog(#"Failed to open/create database");
}
}else{
NSLog(#"File Exist");
}
return isSuccess;
}
-(BOOL) Delete:(NSString *) name{
const char *dbpath = [databasePath UTF8String];
if (sqlite3_open(dbpath, &database) == SQLITE_OK){
NSString *query = [NSString stringWithFormat:#"delete from list where name like '%#'",name];
const char *stmt = [query UTF8String];
sqlite3_prepare_v2(database, stmt,-1, &statement, NULL);
if (sqlite3_step(statement) == SQLITE_DONE){
sqlite3_finalize(statement);
return YES;
}else {
NSLog(#"error: %s",sqlite3_errmsg(database));
sqlite3_finalize(statement);
return NO;
}
}else{
sqlite3_close(database);
return NO;
}
}
-(NSDictionary *) CatList:(NSString *) cat{
const char *dbpath = [databasePath UTF8String];
NSDictionary *dict;
if (sqlite3_open(dbpath, &database) == SQLITE_OK)
{
NSString *querySQL =[NSString stringWithFormat:#"select name,path from list where category like '%#'",cat];
const char *query_stmt = [querySQL UTF8String];
if (sqlite3_prepare_v2(database, query_stmt, -1, &statement, NULL) == SQLITE_OK)
{
// NSLog(#"inside list");
NSMutableArray *arr1 = [[NSMutableArray alloc] init];
NSMutableArray *arr2 = [[NSMutableArray alloc] init];
// NSMutableArray *arr3 = [[NSMutableArray alloc] init];
while(sqlite3_step(statement) == SQLITE_ROW)
{
NSString *name = [[NSString alloc] initWithUTF8String:(const char *) sqlite3_column_text(statement, 0)];
[arr1 addObject:name];
//NSLog(#"%#",name);
NSString *category = [[NSString alloc] initWithUTF8String:(const char *) sqlite3_column_text(statement, 1)];
[arr2 addObject:category];
// //NSLog(#"%#",dept);
// NSString *path = [[NSString alloc] initWithUTF8String:(const char *) sqlite3_column_text(statement, 3)];
// [arr3 addObject:path];
}
sqlite3_finalize(statement);
dict = #{#"name":arr1,#"path":arr2};
//NSLog(#"%#",dict);
}else{
NSLog(#"error: %s",sqlite3_errmsg(database));
}
sqlite3_close(database);
}
return dict;
}
- (BOOL) saveData:(NSString*)name category:(NSString*)category path:(NSString*)path{
const char *dbpath = [databasePath UTF8String];
if (sqlite3_open(dbpath, &database) == SQLITE_OK)
{
NSString *highest = #"select max(sno) from list";
const char *Query = [highest UTF8String];
if (sqlite3_prepare_v2(database, Query, -1, &statement, NULL) == SQLITE_OK){
if (sqlite3_step(statement) == SQLITE_ROW){
int sno = sqlite3_column_int(statement, 0);
NSString *insertSQL = [NSString stringWithFormat:#"insert into list values(\"%d\",\"%#\",\"%#\", \"%#\",\"%d\")",sno+1,name, category, path,0];
const char *insert_stmt = [insertSQL UTF8String];
sqlite3_prepare_v2(database, insert_stmt,-1, &statement, NULL);
if (sqlite3_step(statement) == SQLITE_DONE){
sqlite3_finalize(statement);
return YES;
}else {
sqlite3_finalize(statement);
return NO;
}
}else{
NSString *insertSQL = [NSString stringWithFormat:#"insert into list values(\"%d\",\"%#\",\"%#\", \"%#\",\"%d\")",1,name, category, path,0];
const char *insert_stmt = [insertSQL UTF8String];
sqlite3_prepare_v2(database, insert_stmt,-1, &statement, NULL);
if (sqlite3_step(statement) == SQLITE_DONE){
sqlite3_finalize(statement);
return YES;
}else {
sqlite3_finalize(statement);
return NO;
}
}
}
sqlite3_close(database);
}
return NO;
}
-(BOOL) Fav:(NSString *) name{
const char *dbpath = [databasePath UTF8String];
if (sqlite3_open(dbpath, &database) == SQLITE_OK){
NSString *query = [NSString stringWithFormat:#"update list set fav = 1 where name like '%#'",name];
const char *stmt = [query UTF8String];
sqlite3_prepare_v2(database, stmt,-1, &statement, NULL);
if (sqlite3_step(statement) == SQLITE_DONE){
sqlite3_finalize(statement);
return YES;
}else {
sqlite3_finalize(statement);
return NO;
}
}else{
return NO;
}
}
-(NSArray *) GetListFav{
const char *dbpath = [databasePath UTF8String];
NSArray *dict;
if (sqlite3_open(dbpath, &database) == SQLITE_OK)
{
NSString *querySQL = #"select name from list where fav = 1";
const char *query_stmt = [querySQL UTF8String];
if (sqlite3_prepare_v2(database, query_stmt, -1, &statement, NULL) == SQLITE_OK)
{
NSMutableArray *arr1 = [[NSMutableArray alloc] init];
while(sqlite3_step(statement) == SQLITE_ROW)
{
NSString *name = [[NSString alloc] initWithUTF8String: (const char *) sqlite3_column_text(statement, 0)];
[arr1 addObject:name];
}
sqlite3_finalize(statement);
dict = arr1;
}else{
NSLog(#"error: %s",sqlite3_errmsg(database));
}
sqlite3_close(database);
}
return dict;
}
-(BOOL) removeFav:(NSString *) name{
const char *dbpath = [databasePath UTF8String];
if (sqlite3_open(dbpath, &database) == SQLITE_OK){
NSString *query = [NSString stringWithFormat:#"update list set fav = 0 where name like '%#'",name];
const char *stmt = [query UTF8String];
sqlite3_prepare_v2(database, stmt,-1, &statement, NULL);
if (sqlite3_step(statement) == SQLITE_DONE){
sqlite3_finalize(statement);
return YES;
}else {
sqlite3_finalize(statement);
return NO;
}
}else{
return NO;
}
}
-(NSArray *) GetList{
const char *dbpath = [databasePath UTF8String];
NSArray *dict;
if (sqlite3_open(dbpath, &database) == SQLITE_OK)
{
NSString *querySQL = #"select name from list";
const char *query_stmt = [querySQL UTF8String];
if (sqlite3_prepare_v2(database, query_stmt, -1, &statement, NULL) == SQLITE_OK)
{
//NSLog(#"inside list");
NSMutableArray *arr1 = [[NSMutableArray alloc] init];
while(sqlite3_step(statement) == SQLITE_ROW)
{
NSString *name = [[NSString alloc] initWithUTF8String:(const char *) sqlite3_column_text(statement, 0)];
[arr1 addObject:name];
}
sqlite3_finalize(statement);
dict = arr1;
}else{
NSLog(#"error: %s",sqlite3_errmsg(database));
}
sqlite3_close(database);
}
return dict;
}
#end
You can only access sqllite once at a time. If you have multiple threads, you can run in this situation. Example:
So always try to close database once it is used using:
sqlite3_close(database);
You need to make sure every sqlite3_open is balanced with a sqlite3_close before trying to do sqlite3_open again:
Your saveData method has quite a few return statements that will prevent the database from ever calling sqlite3_close. Make sure all paths out of the method close the database properly. In the end, this means that you'll try to open the database although it's already open.
Or, better, just open the database once and leave it open, eliminating the repeated opening and closing of the database.
Your Delete, Fav, and removeFav methods are also not closing the database.
A few unrelated observations:
You should be wary about using stringWithFormat to build SQL with string parameters. If the string being searched for had a apostrophe in it, your code will fail. Use ? placeholders and then use sqlite3_bind_text to bind values to those placeholders.
If you make your sno column a AUTOINCREMENT, you won't have to do that "get the max sno before inserting new row" logic. Thus, the CREATE statement might look like:
create table if not exists list (
sno integer primary key autoincrement,
name text,
category text,
path text,
fav integer)
You can then omit sno from the INSERT statements, and it will automatically be assigned a unique identifier.

Sqlite database locked error - iOS

I'm using sqlite to use insert and update the data in table view. I can able to update the data only once, on the next attempt it showing database locked. Even though am closing the database, please help. Below is the code.
-(void)saveUserCredential: (NSString *)email :(NSString *)userName :(NSString *)loginTime :(NSString *)source
{
NSDateFormatter *dateformate=[[NSDateFormatter alloc]init];
[dateformate setDateFormat:#"yyyy-MM-dd HH:mm"]; // Date formater
NSString *todayDate = [dateformate stringFromDate:[NSDate date]];
const char *dbpath = [databasePath UTF8String];
if (sqlite3_open(dbpath, &database) == SQLITE_OK)
{
NSString * query = #"SELECT * from users";
int rc =sqlite3_prepare_v2(database, [query UTF8String], -1, &statement, NULL);
if(rc == SQLITE_OK)
{
if(sqlite3_step(statement) == SQLITE_ROW)
{
NSString *updateSQL = [NSString stringWithFormat:#"update users set email = '%#', username = '%#', source = '%#', created = '%#' where id = '%d'",email, userName, source, todayDate,1];
const char *update_stmt = [updateSQL UTF8String];
sqlite3_prepare_v2(database, update_stmt, -1, &statement, NULL );
//sqlite3_bind_int(statement, 1, 1);
if (sqlite3_step(statement) == SQLITE_DONE)
{
NSLog(#"successfully updated");
}
else{
NSLog(#"Error while updating. '%s'", sqlite3_errmsg(database));
}
}
else
{
NSString *insertSQL = [NSString stringWithFormat:#"insert into users (email,username,source,created) values('%#','%#','%#','%#')",email,userName,source,todayDate];
NSLog(#"INS SQL: %#", insertSQL);
const char *insert_stmt = [insertSQL UTF8String];
sqlite3_prepare_v2(database, insert_stmt,-1, &statement, NULL);
if (sqlite3_step(statement) == SQLITE_DONE)
{
NSLog(#"INSERTED");
}
else
{
NSLog(#"NOT INSERTED");
}
NSLog(#"hello ");
}
sqlite3_finalize(statement);
sqlite3_close(database);
}
}
}
You need to call
sqlite3_finalize(statement);
for each successful sqlite_prepare_v2 call. It should be balanced. Also use different sqlite3_stmt for each query.
So your code need to be changed like:
const char *dbpath = [databasePath UTF8String];
if (sqlite3_open(dbpath, &database) == SQLITE_OK)
{
NSString * query = #"SELECT * from users";
int rc =sqlite3_prepare_v2(database, [query UTF8String], -1, &statement, NULL);
if(rc == SQLITE_OK)
{
if(sqlite3_step(statement) == SQLITE_ROW)
{
NSString *updateSQL = [NSString stringWithFormat:#"update users set email = '%#', username = '%#', source = '%#', created = '%#' where id = '%d'",email, userName, source, todayDate,1];
const char *update_stmt = [updateSQL UTF8String];
sqlite3_stmt *upStmt;
sqlite3_prepare_v2(database, update_stmt, -1, &upStmt, NULL );
//sqlite3_bind_int(upStmt, 1, 1);
if (sqlite3_step(upStmt) == SQLITE_DONE)
{
NSLog(#"successfully updated");
}
else
{
NSLog(#"Error while updating. '%s'", sqlite3_errmsg(database));
}
sqlite3_finalize(upStmt);
}
else
{
NSString *insertSQL = [NSString stringWithFormat:#"insert into users (email,username,source,created) values('%#','%#','%#','%#')",email,userName,source,todayDate];
NSLog(#"INS SQL: %#", insertSQL);
const char *insert_stmt = [insertSQL UTF8String];
sqlite3_stmt *inStmt;
sqlite3_prepare_v2(database, insert_stmt,-1, &inStmt, NULL);
if (sqlite3_step(inStmt) == SQLITE_DONE)
{
NSLog(#"INSERTED");
}
else
{
NSLog(#"NOT INSERTED");
}
NSLog(#"hello ");
sqlite3_finalize(inStmt);
}
sqlite3_finalize(statement);
sqlite3_close(database);
}
}

How to prevent duplicate data in SQLite3 in iOS 7?

I am trying to prevent duplicate values in SQlite DB.These are essentially a list of names along with which I am storing date as NSString as well.Now what I want to do is , insert a name only once and if inserted second time I want to update the date for it?So far I am able to insert new record, however not able to update it.What am I missing?
-(NSString *)viewDataBaseForCity:(NSString *)cityName addedDate:(NSString *)dateAdded{
const char *dbpath = [databasePath UTF8String];
if (sqlite3_open(dbpath, &citiesDB)==SQLITE_OK)
{
NSString *querySQL = [NSString stringWithFormat:#"SELECT cityname FROM CITIES WHERE cityname=%#", cityName];
const char *query_stmt = [querySQL UTF8String];
if (sqlite3_prepare_v2(citiesDB, query_stmt, -1, &statement, NULL)== SQLITE_OK)
{
//This part is not executed at all
if (sqlite3_step(statement)==SQLITE_ROW)
{
self.tempcityName = [[NSString alloc]initWithUTF8String:(const char *) sqlite3_column_text(statement, 0)];
NSLog(#"Found city name : -%#",self.tempcityName);
return self.tempcityName;
}else{
NSLog(#"Not Found");
return nil;
}
sqlite3_finalize(statement);
sqlite3_close(citiesDB);
}
}
return nil;
}
-(void)checkforupdate:(NSString *)cityName addedDate:(NSString *)dateAdded{
{
if(tempcityName == cityName)
{
NSString *querySQL = [NSString stringWithFormat:#"UPDATE CITIES set id=%# WHERE cityname=%#", dateAdded, cityName];
const char *query_stmt = [querySQL UTF8String];
if (sqlite3_prepare_v2(citiesDB, query_stmt, -1, &statement, NULL) == SQLITE_OK)
{
NSLog(#"updated successfully");
}
sqlite3_finalize(statement);
sqlite3_close(citiesDB);
}
else
{
[self insertintotable:cityName addedDate:dateAdded];
}
}
}
-(void)insertintotable:(NSString *)cityName addedDate:(NSString *)dateAdded{
{
const char *dbpath = [databasePath UTF8String];
if (sqlite3_open(dbpath, &citiesDB)==SQLITE_OK)
{
NSString *insert_sql = [NSString stringWithFormat:#"INSERT INTO CITIES(cityname,id)VALUES (\"%#\",\"%#\")",cityName,dateAdded];
const char *insert_stmt = [insert_sql UTF8String];
sqlite3_prepare_v2(citiesDB, insert_stmt, -1, &statement, NULL);
if (sqlite3_step(statement)==SQLITE_DONE)
{
NSLog(#"Saved");
}
else{
NSLog(#"NOT Saved");
}
sqlite3_finalize(statement);
sqlite3_close(citiesDB);
}
}
}
Now the fields of table are created as below.
- (void)initDatabase{
//Putting in caches
NSString *cacheDir = [NSSearchPathForDirectoriesInDomains
(NSCachesDirectory, NSUserDomainMask, YES) objectAtIndex:0];
databasePath = [cacheDir
stringByAppendingPathComponent:#"CityList.db"];
NSFileManager *filemgr = [NSFileManager defaultManager];
if ([filemgr fileExistsAtPath:databasePath]==NO) {
const char *dbpath = [databasePath UTF8String];
if (sqlite3_open(dbpath, &citiesDB)==SQLITE_OK) {
char *errMsg;
NSString *sql_stmt = #"CREATE TABLE IF NOT EXISTS CITIES (";
sql_stmt = [sql_stmt stringByAppendingString:#"cityname TEXT PRIMARY KEY UNIQUE, "];
sql_stmt = [sql_stmt stringByAppendingString:#"id TEXT)"];
if (sqlite3_exec(citiesDB, [sql_stmt UTF8String], NULL, NULL, &errMsg)!=SQLITE_OK) {
NSLog(#"Failed to create table");
}
else
{
NSLog(#"CITIES table created successfully");
}
sqlite3_close(citiesDB);
}else {
NSLog(#"Failed to open/create database");
}
}
}
The below code will help you to do what you want. First check for the cityname you are entering if it exists in database table then update if not exists just insert into the database table.
#synthesis tempcityName;
-(BOOL)saveCity:(NSString *)cityName addedDate:(NSString *)dateAdded{
sqlite3_stmt *statement;
const char *dbpath = [databasePath UTF8String];
if (sqlite3_open(dbpath, &citiesDB)==SQLITE_OK)
{
NSString *querySQL = [NSString stringWithFormat:#"SELECT cityname FROM CITIES WHERE cityname=%#", cityName];
const char *query_stmt = [querySQL UTF8String];
if (sqlite3_prepare_v2(citiesDB, query_stmt, -1, &statement, NULL)== SQLITE_OK)
{
if (sqlite3_step(statement)==SQLITE_ROW)
{
tempcityName = [[NSString alloc]initWithUTF8String:(const char *) sqlite3_column_text(statement, 0)];
}
else{
[self.insertintotable:cityName];
}
sqlite3_finalize(statement);
}
sqlite3_close(citiesDB);
[self.checkforupdate:cityName];
}
To check the data is eligible to update or not:
-(void)checkforupdate:(NSString *)cityName
{
if(tempcityName == cityName)
{
NSString *querySQL = [NSString stringWithFormat:#"UPDATE CITIES set id=%# WHERE cityname=%#", dateAdded, cityName];
const char *query_stmt = [querySQL UTF8String];
if (sqlite3_prepare_v2(_beaconDB, query_stmt, -1, &statement, NULL) == SQLITE_OK)
{
NSLog(#"updated successfully");
}
sqlite3_finalize(query_stmt);
sqlite3_close(citiesDB);
}
else
{
[self.insertintotable:cityName];
}
}
If the data is not eligible to update then call to insert in DB table
-(void)insertintotable:(NSString *)cityName
{
sqlite3_stmt *statement;
const char *dbpath = [databasePath UTF8String];
if (sqlite3_open(dbpath, &citiesDB)==SQLITE_OK) {
//This inserts same name multiple times.
NSString *insert_sql = [NSString stringWithFormat:#"INSERT INTO CITIES(cityname,id)VALUES (\"%#\",\"%#\")",cityName,dateAdded];
const char *insert_stmt = [insert_sql UTF8String];
sqlite3_prepare_v2(citiesDB, insert_stmt, -1, &statement, NULL);
if (sqlite3_step(statement)==SQLITE_DONE)
{
NSLog(#"Saved");
return YES;
}
else{
NSLog(#"NOT Saved");
return NO;
}
sqlite3_finalize(statement);
sqlite3_close(citiesDB);
}
First try to update the date.
If this fails (i.e., if sqlite3_changes says no rows were modified), insert a new row:
execute("UPDATE Cities SET id = ? where cityname = ?", ...);
if (sqlite3_changes(citiesDB) == 0) {
execute("INSERT INTO Cities(cityname, id) VALUES(?,?)", ...);
}
First of all you retrieve all data of name from table using Retrieve Query.
if ([RetriveDat containsObject:#"New Data"])
{
// Update Quert
}
else
{
// Insert Query
}

Cannot find updated row SQLite IOS

I have an app where I take details of the user and save it to SQLite db. Also I am able to find the details and display the result.
-(void) createDB{
NSString *docsDir;
NSArray *dirPaths;
// Get the documents directory
dirPaths = NSSearchPathForDirectoriesInDomains(
NSDocumentDirectory, NSUserDomainMask, YES);
docsDir = dirPaths[0];
// Build the path to the database file
_databasePath = [[NSString alloc]
initWithString: [docsDir stringByAppendingPathComponent:
#"contactUnique6.db"]];
NSFileManager *filemgr = [NSFileManager defaultManager];
if ([filemgr fileExistsAtPath: _databasePath ] == NO)
{
const char *dbpath = [_databasePath UTF8String];
if (sqlite3_open(dbpath, &_contactDB) == SQLITE_OK)
{
char *errMsg;
const char *sql_stmt =
"CREATE TABLE IF NOT EXISTS CONTACTS (ID INTEGER PRIMARY KEY AUTOINCREMENT , NAME TEXT , ADDRESS TEXT, PHONE TEXT )";
if (sqlite3_exec(_contactDB, sql_stmt, NULL, NULL, &errMsg) != SQLITE_OK)
{
_status.text = #"Failed to create table";
}
sqlite3_close(_contactDB);
} else {
_status.text = #"Failed to open/create database";
}
}
- (IBAction)saveData:(id)sender {
sqlite3_stmt *statement;
const char *dbpath = [_databasePath UTF8String];
if (sqlite3_open(dbpath, &_contactDB) == SQLITE_OK)
{
NSString *insertSQL = [NSString stringWithFormat:
#"INSERT OR IGNORE INTO CONTACTS (name, address, phone) VALUES (\"%#\", \"%#\", \"%#\")",
_name.text, _address.text, _phone.text];
const char *insert_stmt = [insertSQL UTF8String];
sqlite3_prepare_v2(_contactDB, insert_stmt,
-1, &statement, NULL);
if (sqlite3_step(statement) == SQLITE_DONE)
{
_status.text = #"Contact added";
_name.text = #"";
_address.text = #"";
_phone.text = #"";
} else {
_status.text = #"Failed to add contact";
}
sqlite3_finalize(statement);
sqlite3_close(_contactDB);
}
}
- (IBAction)findContact:(id)sender {
const char *dbpath = [_databasePath UTF8String];
sqlite3_stmt *statement;
if (sqlite3_open(dbpath, &_contactDB) == SQLITE_OK)
{
NSString *querySQL = [NSString stringWithFormat:
#"SELECT address, phone FROM contacts WHERE name=\"%#\"",
_name.text];
const char *query_stmt = [querySQL UTF8String];
if (sqlite3_prepare_v2(_contactDB,
query_stmt, -1, &statement, NULL) == SQLITE_OK)
{
if (sqlite3_step(statement) == SQLITE_ROW)
{
NSString *addressField = [[NSString alloc]
initWithUTF8String:
(const char *) sqlite3_column_text(
statement, 0)];
_address.text = addressField;
NSString *phoneField = [[NSString alloc]
initWithUTF8String:(const char *)
sqlite3_column_text(statement, 1)];
_phone.text = phoneField;
_status.text = #"Match found";
} else {
_status.text = #"Match not found";
_address.text = #"";
_phone.text = #"";
}
sqlite3_finalize(statement);
}
sqlite3_close(_contactDB);
}
}
The above code is working good. However when I am trying to use an update, it is not displaying when I try to find it. It gives me a match not found even though the contact was saved.
This is the code by which I am trying to update:
- (IBAction)saveData:(id)sender {
sqlite3_stmt *statement;
const char *dbpath = [_databasePath UTF8String];
if (sqlite3_open(dbpath, &_contactDB) == SQLITE_OK)
{
NSString *insertSQL = [NSString stringWithFormat:
#"INSERT OR IGNORE INTO CONTACTS (name, address, phone) VALUES (\"%#\", \"%#\", \"%#\")",
_name.text, _address.text, _phone.text];
insertSQL = [NSString stringWithFormat:
#"UPDATE CONTACTS SET name=\"%#\", address=\"%#\", phone=\"%#\"",
_name.text, _address.text, _phone.text];
const char *insert_stmt = [insertSQL UTF8String];
sqlite3_prepare_v2(_contactDB, insert_stmt,
-1, &statement, NULL);
if (sqlite3_step(statement) == SQLITE_DONE)
{
_status.text = #"Contact added";
_name.text = #"";
_address.text = #"";
_phone.text = #"";
} else {
_status.text = #"Failed to add contact";
}
sqlite3_finalize(statement);
sqlite3_close(_contactDB);
}
}
Basically my aim is to be able to save-update-find. (without losing the primary key on update, as I have FK relations)
EDIT
This is my create db method
-(void) createDB{
NSString *docsDir;
NSArray *dirPaths;
// Get the documents directory
dirPaths = NSSearchPathForDirectoriesInDomains(
NSDocumentDirectory, NSUserDomainMask, YES);
docsDir = dirPaths[0];
// Build the path to the database file
_databasePath = [[NSString alloc]
initWithString: [docsDir stringByAppendingPathComponent:
#"contactUnique6.db"]];
NSFileManager *filemgr = [NSFileManager defaultManager];
if ([filemgr fileExistsAtPath: _databasePath ] == NO)
{
const char *dbpath = [_databasePath UTF8String];
if (sqlite3_open(dbpath, &_contactDB) == SQLITE_OK)
{
char *errMsg;
const char *sql_stmt =
"CREATE TABLE IF NOT EXISTS CONTACTS (ID INTEGER PRIMARY KEY AUTOINCREMENT , NAME TEXT , ADDRESS TEXT, PHONE TEXT )";
if (sqlite3_exec(_contactDB, sql_stmt, NULL, NULL, &errMsg) != SQLITE_OK)
{
_status.text = #"Failed to create table";
}
sqlite3_close(_contactDB);
} else {
_status.text = #"Failed to open/create database";
}
}
i cant get your second -(IBAction)saveData:(id)sender {} method [ Third code block ]..
You said above 2 blocks are working properly so its ok.
i think you embedded the update's logic in insert's logic i.e. you embedded the update method in your saveData method..
Here i cant get what u have done, so instead of code here i m providing the template for update query, just put your code in it...
sqlite3_stmt *statement;
if(sqlite3_open(dbpath, &database_object) == SQLITE_OK)
{
NSString *sql = [NSString stringWithFormat:#"update table_name set column_name = \"%#\"", Your_value];
const char *sql_stmt = [sql UTF8String];
if(sqlite3_prepare_v2(database_object , sql_stmt, -1, &statement, NULL) != SQLITE_OK)
NSLog(#"Error while creating update statement. '%s'", sqlite3_errmsg(database_object));
if(SQLITE_DONE != sqlite3_step(statement))
NSLog(#"Error while updating. '%s'", sqlite3_errmsg(database_object));
sqlite3_finalize(statement);
}
Go with this template, i think it will work for you...

SQLite iOS Insert data

Im trying to insert just one name to my sqlite file. im using this code but it's not working :/
-(void)InsertRecords:(NSMutableString *) txt{
if(addStmt == nil) {
const char *sql = "INSERT INTO myMovies (movieName) VALUES(?) ";
if(sqlite3_prepare_v2(database, sql, -1, &addStmt, NULL) != SQLITE_OK)
NSAssert1(0, #"Error while creating add statement. '%s'", sqlite3_errmsg(database));
else
sqlite3_bind_text(addStmt, 1, [txt UTF8String], -1, SQLITE_TRANSIENT);
}
if(SQLITE_DONE != sqlite3_step(addStmt))
NSAssert1(0, #"Error while inserting data. '%s'", sqlite3_errmsg(database));
else
sqlite3_reset(addStmt);
}
pass your query to this method and try,
-(void)Insertdata:(NSString*)query{
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *databasePath = [documentsDirectory stringByAppendingPathComponent:#"YourDBName.sql"];
if(sqlite3_open([databasePath UTF8String],&db) == SQLITE_OK)
{
NSString *querySQL = [NSString stringWithFormat: #"%#",query];
char *errmsg=nil;
if(sqlite3_exec(db, [querySQL UTF8String], NULL, NULL, &errmsg)==SQLITE_OK)
{
NSLog(#".. Row Added ..");
}
}
sqlite3_close(db);
}
An "out of memory" error from sqlite typically means the database handle you are using hasn't been opened yet. Make sure you are calling sqlite3_open_v2 with the database variable shown in the code you posted?
ok finally I made it ! this is the code that I used for everyone who need it :
-(void)InsertRecords:(NSMutableString *)txt{
NSString *dbPath = [[[NSBundle mainBundle] resourcePath ]stringByAppendingPathComponent:#"movieData.sqlite"];
const char *dbpath = [dbPath UTF8String];
sqlite3 *contactDB;
sqlite3_stmt *statement;
NSLog(#"%#",dbPath);
if (sqlite3_open(dbpath, &contactDB) == SQLITE_OK)
{
NSString *insertSQL = [NSString stringWithFormat: #"INSERT INTO myMovies (movieName) VALUES (\"%#\")", txt];
const char *insert_stmt = [insertSQL UTF8String];
sqlite3_prepare_v2(contactDB, insert_stmt, -1, &statement, NULL);
if (sqlite3_step(statement) == SQLITE_DONE)
{
sqlite3_bind_text(statement, 1, [txt UTF8String], -1, SQLITE_TRANSIENT);
} else {
NSLog(#"error");
}
sqlite3_finalize(statement);
sqlite3_close(contactDB);
}
}
Try this:
//save our data
- (BOOL) saveEmployee:(Employee *)employee
{
BOOL success = false;
sqlite3_stmt *statement = NULL;
const char *dbpath = [databasePath UTF8String];
if (sqlite3_open(dbpath, &mySqliteDB) == SQLITE_OK)
{
if (employee.employeeID > 0) {
NSLog(#"Exitsing data, Update Please");
NSString *updateSQL = [NSString stringWithFormat:#"UPDATE EMPLOYEES set name = '%#', department = '%#', age = '%#' WHERE id = ?",
employee.name,
employee.department,
[NSString stringWithFormat:#"%d", employee.age]];
const char *update_stmt = [updateSQL UTF8String];
sqlite3_prepare_v2(mySqliteDB, update_stmt, -1, &statement, NULL );
sqlite3_bind_int(statement, 1, employee.employeeID);
if (sqlite3_step(statement) == SQLITE_DONE)
{
success = true;
}
}
else{
NSLog(#"New data, Insert Please");
NSString *insertSQL = [NSString stringWithFormat:
#"INSERT INTO EMPLOYEES (name, department, age) VALUES (\"%#\", \"%#\", \"%#\")",
employee.name,
employee.department,
[NSString stringWithFormat:#"%d", employee.age]];
const char *insert_stmt = [insertSQL UTF8String];
sqlite3_prepare_v2(mySqliteDB, insert_stmt, -1, &statement, NULL);
if (sqlite3_step(statement) == SQLITE_DONE)
{
success = true;
}
}
sqlite3_finalize(statement);
sqlite3_close(mySqliteDB);
}
return success;
}

Resources