SQLite3 not updating in iOS application - ios

I have a table called Budgets that stores its settings, values, and a purchases nsarray full of the object purchases.
I am not sure what I am doing wrong in my method right here, but it will not update the database on an existing entry. It saves a new budget just fine.
- (BOOL) saveBudget:(Budget *)budget
{
BOOL success = false;
sqlite3_stmt *statement = NULL;
const char *dbpath = [databasePath UTF8String];
if (sqlite3_open(dbpath, &database) == SQLITE_OK)
{
if (budget.budgetID > 0) {
NSLog(#"Existing data, Update Please");
NSString *updateSQL = [NSString stringWithFormat:#"UPDATE BUDGETS set name = '%#', budget = '%#', customdate = '%d', customday = '%d', rolloverp = '%d', rollovern = '%d', purchases = ?8 WHERE id = ?", budget.name, budget.budget, budget.customDate, budget.customDay, budget.rolloverP, budget.rolloverN];
const char *update_stmt = [updateSQL UTF8String];
sqlite3_prepare_v2(database, update_stmt, -1, &statement, NULL);
sqlite3_bind_int(statement, 1, budget.budgetID);
sqlite3_bind_blob(statement, 8, [budget.purchases bytes], [budget.purchases length], SQLITE_TRANSIENT);
if (sqlite3_step(statement) == SQLITE_DONE)
{
success = true;
}
}
else
{
NSLog(#"New data, Insert Please");
NSString *insertSQL = [NSString stringWithFormat:#"INSERT INTO BUDGETS (name, budget, customdate, customday, rolloverp, rollovern, purchases) VALUES (\"%#\", \"%#\", \"%d\", \"%d\", \"%d\", \"%d\", ?8)", budget.name, budget.budget, budget.customDate, budget.customDay, budget.rolloverP, budget.rolloverN];
const char *insert_stmt = [insertSQL UTF8String];
sqlite3_prepare_v2(database, insert_stmt, -1, &statement, NULL);
sqlite3_bind_blob(statement, 8, [budget.purchases bytes], [budget.purchases length], SQLITE_TRANSIENT);
if (sqlite3_step(statement) == SQLITE_DONE)
{
success = true;
}
}
sqlite3_finalize(statement);
sqlite3_close(database);
NSLog(#"Save Success");
}
return success;
}
I am assuming that the query is incorrect, but I may be wrong.
EDIT:
Here is how I am adding the database. Again, new entries are added and retrieved from the database just fine. Old entries are retrieved but will not update.
- (void) initDatabase
{
NSString *docsDir;
NSArray *dirPaths;
dirPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
docsDir = [dirPaths objectAtIndex:0];
databasePath = [[NSString alloc] initWithString:
[docsDir stringByAppendingPathComponent:#"budget.db"]];
NSFileManager *filemgr = [NSFileManager defaultManager];
if([filemgr fileExistsAtPath:databasePath] == NO)
{
const char *dbpath = [databasePath UTF8String];
if (sqlite3_open(dbpath, &database) == SQLITE_OK)
{
NSString sql_stmt = #"CREATE TABLE IF NOT EXISTS BUDGETS (";
sql_stmt = [sql_stmt stringByAppendingString:#"id INTEGER PRIMARY KEY AUTOINCREMENT, "];
sql_stmt = [sql_stmt stringByAppendingString:#"name TEXT, "];
sql_stmt = [sql_stmt stringByAppendingString:#"budget DOUBLE, "];
sql_stmt = [sql_stmt stringByAppendingString:#"customdate INTEGER, "];
sql_stmt = [sql_stmt stringByAppendingString:#"customday INTEGER, "];
sql_stmt = [sql_stmt stringByAppendingString:#"rolloverp INTEGER, "];
sql_stmt = [sql_stmt stringByAppendingString:#"rollovern INTEGER, "];
sql_stmt = [sql_stmt stringByAppendingString:#"purchases BLOB)"];
if (sqlite3_exec(database, [sql_stmt UTF8String], NULL, NULL, &errMsg) != SQLITE_OK)
{
NSLog(#"Failed to create table BUDGETS");
}
else
{
NSLog(#"BUDGETS table created successfully");
}
sqlite3_close(database);
}
else
{
NSLog(#"Failed to open/create database");
}
}
}
ANOTHER QUESTION:
I also have a question on whether I am saving the purchases NSArray correctly or not. I assumed that this would work.

Make sure the Location your pointing to the SQlite data base is right.And before executing the query make sure the table is in open state and ready to the operation. Refer this code:
sqlite3_stmt *statement;
sqlite3 *cPDB;
NSString *docsDir;
NSArray *dirPaths;
dirPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
docsDir = [dirPaths objectAtIndex:0];
// Data base path
databasePath = [[NSString alloc] initWithString: [docsDir stringByAppendingPathComponent: #"cPDB.db"]];
const char *dbpath = [databasePath UTF8String];
if (sqlite3_open(dbpath, &cPDB) == SQLITE_OK)
{
NSString *querySQL = [NSString stringWithFormat: #"UPDATE USER_SESSION_INFO SET \"%#\" = \"%#\", synState = 'false' WHERE sessionName=\"%#\"",categoryTy,state,sessionName];
const char *query_stmt = [querySQL UTF8String];
if (sqlite3_prepare_v2(cPDB, query_stmt, -1, &statement, NULL) == SQLITE_OK)
{
if((sqlite3_step(statement)) != SQLITE_DONE)
NSLog(#"Not Updated");
else
{
NSLog(#"Succesfully updated row !");
return YES;
}
}
}

Found the problem. There were no single quotes around ?8 in the update statement. Well, its always the small problems. Thanks everyone!

Related

Sqlite Error - "Insertion Failure: unable to open database file"

I'm using NSTimer to call the below function every second and and pass the values for activityType and activityConfidence using parameters. After some successful insertions I'm getting an error "unable to open database file"
-(void)tableInsertionFunction:(NSString *)activityType confidenceIs:(NSString *)activityConfidence
{
dirPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
docsDir = dirPaths[0];
databasePath = [docsDir stringByAppendingPathComponent:#"mainSDK.db"];
dbpath = [databasePath UTF8String];
if (sqlite3_open(dbpath, & demoDB) == SQLITE_OK) {
NSString *insertStatement = [NSString stringWithFormat: #"INSERT INTO activityTable ( activityType , activityConfidence) VALUES ('%#' , '%#' )",activityType, activityConfidence];
sqlite3_stmt *statement;
const char *insert_stmt = [insertStatement UTF8String];
sqlite3_prepare_v2(demoDB, insert_stmt,-1, &statement, NULL);
if (sqlite3_step(statement) == SQLITE_DONE) {
NSLog(#"Insertion Successful");
}
else {
NSLog(#"Insertion Failure: %s",sqlite3_errmsg(demoDB));
}
sqlite3_close(demoDB);
}
}

Data not inserting into sqlite database

Hi in my application I have data which want insert into my sqlite database .So I have already created the database successfully, But the problem its not insert data into database.
My database creation code.
- (void)createDatabase
{
NSArray *directories = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *doctumentsDirectory = [directories lastObject];
self.databasePath = [[NSString alloc] initWithString:[doctumentsDirectory stringByAppendingPathComponent:#"/bp.sqlite"]];
NSFileManager *fileManager = [NSFileManager defaultManager];
// create DB if it does not already exists
if (![fileManager fileExistsAtPath:self.databasePath]) {
const char *dbPath = [self.databasePath UTF8String];
if (sqlite3_open(dbPath, &_myDataBase) == SQLITE_OK) {
char *errorMsg;
const char *sql_statement = "CREATE TABLE IF NOT EXISTS br (ID INTEGER PRIMARY KEY AUTOINCREMENT, NAME TEXT, COST TEXT,QUTY TEXT)";
if (sqlite3_exec(_myDataBase, sql_statement, NULL, NULL, &errorMsg) != SQLITE_OK) {
[self errorCreatingTable:[NSString stringWithFormat:#"failed creating table. ERROR:%s", errorMsg]];
}
sqlite3_close(_myDataBase);
} else {
[self errorCreatingTable:#"failed openning / creating table"];
}
}
}
My insert code i have UIButton action method where i give my insert code.
-(void)aMethod2:(UIButton*)sender
{
NSString *inr=[intarr objectAtIndex:sender.tag];
NSLog(#"%#",inr);
NSString *item=[self.menuarray objectAtIndex:sender.tag];
NSLog(#"%#",item);
NSString *cost=[self.menuarray1 objectAtIndex:sender.tag];
NSLog(#"%#",cost);
NSString *sql = [NSString stringWithFormat:#"INSERT INTO br ('NAME','COST','QUTY') VALUES ('%#','%#','%#')",item,cost,inr];
NSLog(#"%#",sql);
}
I have used the above code where get the data and inserting into my database but values all passing correctly problem is its not inserting into my database please tell me how to resolve this issue I have been stuck here for long time help me out.
Thanks.
When i saw your question, i couldn't help seeing something that was a bit strange to me... and that was seeing my own code. thanks for using my code snippet from stackoverflow :) getting error while trying to create sqlite database 'Could not create table' IOS7
Any way, here is a quick example on how to insert:
- (void)insertDictionaryToDataBase:(NSDictionary *)dictionary
{
if (dictionary) {
sqlite3_stmt *sql_statement;
const char *dbPath = [self.databasePath UTF8String];
if (sqlite3_open(dbPath, &_inboxDatabase) == SQLITE_OK) {
NSString *insertSQL = [NSString stringWithFormat:#"INSERT INTO MY_TABLE_NAME (COLUMN_A, COLUMN_B, COLUMN_C) VALUES (?,?,?)"];
const char *insertStatement = [insertSQL UTF8String];
sqlite3_prepare_v2(_inboxDatabase, insertStatement, -1, &sql_statement, NULL);
sqlite3_bind_text(sql_statement, 1, [dictionary[#"key1"] UTF8String], -1, SQLITE_TRANSIENT);
sqlite3_bind_text(sql_statement, 2, [dictionary[#"key2"] UTF8String], -1, SQLITE_TRANSIENT);
sqlite3_bind_int(sql_statement, 3, [dictionary[#"key3"] intValue]);
if (sqlite3_step(sql_statement) == SQLITE_DONE) {
NSLog(#"sucess!");
}
sqlite3_finalize(sql_statement);
sqlite3_close(_inboxDatabase);
}
}
}
DBmanager.h file
#import <Foundation/Foundation.h>
#import <sqlite3.h>
#interface DBReadWriteUtil : NSObject
+(sqlite3*)copyDbToDocumentsDirectoryIfNotExist;
+(BOOL)insertData:(NSString*)arg1 cost:(int)arg2 quty:(int)arg3;
+(NSDictionary*)getUploadPendingMedia;
+(int)removeMediaPOStFormId:(int)row_id;
#end
DBmanager.m file
#import "DBReadWriteUtil.h"
#implementation DBReadWriteUtil
+(sqlite3*)copyDbToDocumentsDirectoryIfNotExist{
NSString *dbPath = [NSTemporaryDirectory() stringByAppendingPathComponent:#"bp.sqlite"];
NSFileManager *fileManager = [NSFileManager defaultManager];
if(![fileManager fileExistsAtPath:dbPath]) {
NSString *localDB = [[NSBundle mainBundle] pathForResource:#"bp" ofType:#"sqlite"];
NSError *err;
if(![fileManager copyItemAtPath:localDB toPath:dbPath error:&err]){
if (DEBUG_MODE) {
NSLog(#"SQL: Not ABLE TO COPY FILE -> %#",err);
}
}
}
sqlite3 *db_connction;
if(sqlite3_open([dbPath UTF8String], &db_connction) != SQLITE_OK){
if (DEBUG_MODE) {
NSLog(#"SQL : Not ABLE TO CONNECT DB:");
}
}
return db_connction;
}
+(BOOL)insertData:(NSString*)arg1 cost:(int)arg2 quty:(int)arg3{
BOOL dbStatus = NO;
sqlite3 *db_connction = [DBReadWriteUtil copyDbToDocumentsDirectoryIfNotExist];
sqlite3_stmt *compiledStmt;
const char *query = "insert into br(NAME,cost,quay) values(?,?,?)";
if(sqlite3_prepare_v2(db_connction, query, -1, &compiledStmt, NULL) == SQLITE_OK ){
sqlite3_bind_text(compiledStmt,1,[arg1 UTF8String],-1,SQLITE_TRANSIENT);
sqlite3_bind_int(compiledStmt, 2, arg2);
sqlite3_bind_int(compiledStmt,3, arg3,-1);
NSUInteger err = sqlite3_step(compiledStmt);
if (err != SQLITE_DONE){
if(DEBUG_MODE){
NSLog(#"error while Inserting image %d %s",err, sqlite3_errmsg(db_connction));
}
}else{
dbStatus = YES;
}
}
sqlite3_finalize(compiledStmt);
sqlite3_close(db_connction);
return dbStatus;
}
Call DBmanager
BOOL successDB = [DBReadWriteUtil insertData: arg1 cost:arg2 quty:arg3];
try this code...
-(void)Insertdata:(NSString*)query{
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *databasePath = [documentsDirectory stringByAppendingPathComponent:#"bp.sqlite"];
NSLog(#"%#",databasePath);
if(sqlite3_open([databasePath UTF8String],&_myDataBase) == SQLITE_OK)
{
NSString *querySQL = [NSString stringWithFormat: #"%#",query];
char *errmsg=nil;
if(sqlite3_exec(_myDataBase, [querySQL UTF8String], NULL, NULL, &errmsg)==SQLITE_OK)
{
NSLog(#".. Inserted ..");
}
}
sqlite3_close(_myDataBase);
}

Add table to existing database IOS sqlite [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question appears to be off-topic because it lacks sufficient information to diagnose the problem. Describe your problem in more detail or include a minimal example in the question itself.
Closed 9 years ago.
Improve this question
I am using SQLite DB in my iOS app. In my screen 1, I was successfully able to create a Database, a table, insert into it and retrieve from it.
However from screen 2 when I am trying to create a table in the same database and insert values, I am unable to.
This is the code which I am using.
-(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:
#"coning.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 order (ID INTEGER PRIMARY KEY AUTOINCREMENT , NAME TEXT UNIQUE , ADDRESS TEXT UNIQUE, PHONE TEXT UNIQUE)";
if (sqlite3_exec(_contactDB, sql_stmt, NULL, NULL, &errMsg) != SQLITE_OK)
{
NSLog(#"Failed to create table");
}
sqlite3_close(_contactDB);
} else {
NSLog(#"Failed to open/create database");
}
}
}
- (void)saveData {
sqlite3_stmt *statement;
const char *dbpath = [_databasePath UTF8String];
if (sqlite3_open(dbpath, &_contactDB) == SQLITE_OK)
{
NSString *insertSQL = [NSString stringWithFormat:
#"INSERT OR REPLACE INTO order (name, address, phone) VALUES (\"%#\", \"%#\", \"%#\")",
#"name", #"address", #"phone"];
const char *insert_stmt = [insertSQL UTF8String];
sqlite3_prepare_v2(_contactDB, insert_stmt,
-1, &statement, NULL);
if (sqlite3_step(statement) == SQLITE_DONE)
{
NSLog(#"added");
} else {
NSLog(#"Failed to add contact");
}
sqlite3_finalize(statement);
sqlite3_close(_contactDB);
}
}
I have been using the same code to add entries in table 1 but when I do the same to create table 2, its says 'Failed to add contact'. Can someone suggest where I might be going wrong?
Also I want to make the PK of table 1 as a FK in table 2.
You can use sqlite3_exec() method instead of sqlite3_step().
sqlite3_exec() will execute whatever the query you have given.
I am sure, It will definitely help you.
-(BOOL)createNewTableInExistingDb
{
NSArray *array=NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *filePath=[array objectAtIndex:0];
filePath =[filePath stringByAppendingPathComponent:#"database.db"];
NSFileManager *manager=[NSFileManager defaultManager];
BOOL success = NO;
if ([manager fileExistsAtPath:filePath])
{
success =YES;
}
if (!success)
{
NSString *path2=[[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:#"database.db"];
success =[manager copyItemAtPath:path2 toPath:filePath error:nil];
}
createStmt = nil;
NSString *tableName=#"SecondTable";
if (sqlite3_open([filePath UTF8String], &database) == SQLITE_OK) {
if (createStmt == nil) {
NSString *query=[NSString stringWithFormat:#"create table %#(RegNo integer, name text)",tableName];
if (sqlite3_prepare_v2(database, [query UTF8String], -1, &createStmt, NULL) != SQLITE_OK) {
return NO;
}
sqlite3_exec(database, [query UTF8String], NULL, NULL, NULL);
return YES;
}
}
return YES;
}

what does if exist return

I am using sqlite3 as my database for ios project and would like to execute if exist statement to see whether the object exists and if does, update or else insert.
I am using this function to query the database
-(void)updateStatus:(NSString *)queryString {
NSString *docsDir;
NSArray *dirPaths;
dirPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
docsDir = [dirPaths objectAtIndex:0];
m_singleton = [Singleton sharedSingleton];
strDatabasePath = [NSString stringWithString:[docsDir stringByAppendingPathComponent:#"BorneoMotors.db"]];
NSFileManager *filemgr = [NSFileManager defaultManager];
if ([filemgr fileExistsAtPath: strDatabasePath] == YES)
{
const char *dbpath = [strDatabasePath UTF8String];
if (sqlite3_open(dbpath, &sqlDatabase) == SQLITE_OK)
{
const char* beginString = "BEGIN;";
sqlite3_stmt *compiledstatement;
sqlite3_prepare_v2(sqlDatabase, beginString, -1, &compiledstatement, NULL);
if (sqlite3_step(compiledstatement) == SQLITE_DONE) {}
else NSLog(#"Failed!");
sqlite3_finalize(compiledstatement);
NSLog(#"QUERY : %#",queryString);
const char *selectStatement = [queryString UTF8String];
sqlite3_prepare_v2(sqlDatabase, selectStatement, -1, &compiledstatement, NULL);
//sqlite3_bind_text(compiledstatement,1,[statusString UTF8String],-1,SQLITE_TRANSIENT);
if (sqlite3_step(compiledstatement) == SQLITE_DONE) {}
else NSLog(#"Failed!");
sqlite3_finalize(compiledstatement);
const char* endString="END;";
sqlite3_prepare_v2(sqlDatabase, endString, -1, &compiledstatement, NULL);
if (sqlite3_step(compiledstatement) == SQLITE_DONE) {}
else NSLog(#"Failed!");
sqlite3_finalize(compiledstatement);
sqlite3_close(sqlDatabase);
}
else NSLog(#"Failed to open table");
}
}
The problem i have is that what this if exists will return and how do i move upon that.
NSString *checkstring = [NSString stringWithFormat:#"IF EXISTS (SELECT * FROM DATABASE WHERE id = %#",cars.ID];
DB *accessdb = [[DB alloc] init];
[accessdb updateStatus:checkstring];
if (??){
NSString *queryString = [NSString stringWithFormat: #"UPDATE DATABASE SET STATUS='%#' WHERE \"DATABASEID\" = '%#'", cars.status,cars.ID];
const char *selectStatement = [queryString UTF8String];
sqlite3_prepare_v2(sqlDatabase, selectStatement, -1, &statement, NULL);
//sqlite3_bind_text(compiledstatement,1,[statusString UTF8String],-1,SQLITE_TRANSIENT);
if (sqlite3_step(statement) == SQLITE_DONE) {}
else NSLog(#"Failed!");
sqlite3_finalize(statement);
}else{
insert}
How do i check whether the existence of the object? What does the if exists return? Need some guidance...
SQLite does not have an IF statement.
To check whether some record exist, just execute a query like
SELECT 1 FROM database WHERE ID = ?
and test in your app whether or not you get back a record.
For your update/insert problem: If you have a unique index on the key colum, you could use the INSERT OR REPLACE command which automatically deletes the old record if the new one would create a duplicate.

iOS SQLite - Max() Function

I have an SQLite database in my iOS application. I'm trying to use the SQL function MAX()
- (void) getMaxTime {
if (sqlite3_open([databasePath UTF8String], &timingsDatabase) == SQLITE_OK)
{
NSString *maxTimeStatement = [NSString stringWithFormat:#" SELECT max(NUMBERS) FROM TIMINGS"];
sqlite3_stmt *statement;
if(sqlite3_prepare_v2(timingsDatabase, [maxTimeStatement UTF8String], -1, &statement, nil) == SQLITE_OK){
while (sqlite3_step(statement) == SQLITE_ROW) {
massimo = sqlite3_column_int(statement, 0);
NSLog(#"The maximun time is %d seconds ", massimo);
}
sqlite3_finalize(statement);
sqlite3_close(timingsDatabase);
}
}
All the numbers in the column NUMBERS have 6 digits after the coma.
Everything works fine if all the numbers are > 10 or all the numbers are <10.
But (example) when I try to get the max among:
1.339670
2.955537
11.355558
It prints: "The maximun time is 2 seconds" (instead of 11)! I'm struggling to understand why.
*EDIT
This is how my Database was created:
-(void)createDatabase
{
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
databasePath = [[NSString alloc]initWithString:[documentsDirectory stringByAppendingPathComponent:#"timings.db"]];
if ([[NSFileManager defaultManager] fileExistsAtPath:databasePath] == FALSE)
{
if (sqlite3_open([databasePath UTF8String], &timingsDatabase) == SQLITE_OK)
{
const char *sqlStatement = "CREATE TABLE IF NOT EXISTS TIMINGS (ID INTEGER PRIMARY KEY AUTOINCREMENT, TIMESTAMP TEXT, TIMING TEXT, NUMBERS TEXT)";
char *error;
sqlite3_exec(timingsDatabase, sqlStatement, NULL, NULL, &error);
sqlite3_close(timingsDatabase);
}
}
}
And this is how timings are stored:
-(void)storeTiming
{
if (sqlite3_open([databasePath UTF8String], &timingsDatabase) == SQLITE_OK)
{
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:#"HH:mm:ss.SSS"];
NSString *insertStatement = [NSString stringWithFormat:#"INSERT INTO TIMINGS (TIMESTAMP, TIMING, NUMBERS) VALUES (\"%#\", \"%#\", \"%f\")", [dateFormatter stringFromDate:startDate], stopWatchLabel.text , intervallo] ;
char *error;
sqlite3_exec(timingsDatabase, [insertStatement UTF8String], NULL, NULL, &error);
sqlite3_close(timingsDatabase);
}
}
Seems that column's data type is string... You should change it to float to use MAX() function.

Resources