I have two databases.
ch_coins.db is read-only data for tableview in [NSBundle mainBundle].
User_data.sqlite in Documents
I try to combine select from both databases and fill data to object. My method is like that:
-(NSMutableArray*)returnSubCountries
{
NSString *path = [[[NSBundle mainBundle] resourcePath]
stringByAppendingPathComponent:databaseName];
NSArray *paths = NSSearchPathForDirectoriesInDomains (NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDir = [paths objectAtIndex:0];
NSString *userDB = [documentsDir stringByAppendingPathComponent:user_data];
NSMutableArray *subCountiresArr=[[NSMutableArray alloc]init];
if (sqlite3_open([path UTF8String], &database) == SQLITE_OK)
{
/*const char *sqlSubCountries="SELECT subCountryID,subCountryName,subCountryComment,image,priority,hasRegions,navigationKey\
FROM subCountries\
ORDER BY priority ASC";*/
const char *sqlSubCountries="SELECT subCountryID,subCountryName,subCountryComment,image,priority,hasRegions,navigationKey,usdb.quantity\
attach database 'userDB' as usdb\
INNER JOIN usdb on subCountries.subCountryID=usdb.refID\
FROM subCountries\
ORDER BY priority ASC";
sqlite3_stmt *statement;
int sqlResult = sqlite3_prepare_v2(database, sqlSubCountries, -1, &statement, NULL);
if ( sqlResult== SQLITE_OK)
{
while (sqlite3_step(statement) == SQLITE_ROW)
{
SubCountry *sbCountryObj=[[SubCountry alloc]init];
sbCountryObj.subCountryID=sqlite3_column_int(statement, 0);
char *subCountryName=(char *)sqlite3_column_text(statement, 1);
char *subCountryComment=(char *)sqlite3_column_text(statement, 2);
char *image=(char *)sqlite3_column_text(statement, 3);
sbCountryObj.priority=sqlite3_column_int(statement, 4);
sbCountryObj.hasRegions=(sqlite3_column_int(statement, 5)==1);
sbCountryObj.navigationKey=sqlite3_column_int(statement, 6);
sbCountryObj.quantity=sqlite3_column_int(statement, 7);
sbCountryObj.subCountryName=(subCountryName)?[NSString stringWithUTF8String:subCountryName]: #"";
sbCountryObj.subCountryComment=(subCountryComment)?[NSString stringWithUTF8String:subCountryComment]: #"";
sbCountryObj.image=(image)?[NSString stringWithUTF8String:image]: #"";
[subCountiresArr addObject:sbCountryObj];
}
sqlite3_finalize(statement);
sqlite3_close(database);
}
}
else
{
//[self dbConnectionError];
}
return subCountiresArr;
}
I must be doing something wrong. any help is much appreciated. Thanx.
EDIT:
-(NSMutableArray*)returnSubCountries
{
NSString *path = [[[NSBundle mainBundle] resourcePath]
stringByAppendingPathComponent:databaseName];
NSArray *paths = NSSearchPathForDirectoriesInDomains (NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDir = [paths objectAtIndex:0];
NSString *userDB = [documentsDir stringByAppendingPathComponent:user_data];
NSMutableArray *subCountiresArr=[[NSMutableArray alloc]init];
if (sqlite3_open([path UTF8String], &database) == SQLITE_OK)
{
/*const char *sqlSubCountries="SELECT subCountryID,subCountryName,subCountryComment,image,priority,hasRegions,navigationKey\
FROM subCountries\
ORDER BY priority ASC";*/
NSString *userDBName = [NSString stringWithFormat:#"attach database '%#' as usdb", userDB];
const char *sqlAttachedDatabase = [userDBName UTF8String];
const char *sqlSubCountries="SELECT subCountryID,subCountryName,subCountryComment,image,priority,hasRegions,navigationKey,usdb.quantity\
sqlAttachedDatabase userDB as usdb\
INNER JOIN usdb on subCountries.subCountryID=usdb.refID\
FROM subCountries\
ORDER BY priority ASC";
sqlite3_stmt *statement;
int sqlResult = sqlite3_prepare_v2(database, sqlSubCountries, -1, &statement, NULL);
if ( sqlResult== SQLITE_OK)
{
while (sqlite3_step(statement) == SQLITE_ROW)
{
SubCountry *sbCountryObj=[[SubCountry alloc]init];
sbCountryObj.subCountryID=sqlite3_column_int(statement, 0);
char *subCountryName=(char *)sqlite3_column_text(statement, 1);
char *subCountryComment=(char *)sqlite3_column_text(statement, 2);
char *image=(char *)sqlite3_column_text(statement, 3);
sbCountryObj.priority=sqlite3_column_int(statement, 4);
sbCountryObj.hasRegions=(sqlite3_column_int(statement, 5)==1);
sbCountryObj.navigationKey=sqlite3_column_int(statement, 6);
sbCountryObj.quantity=sqlite3_column_int(statement, 7);
sbCountryObj.subCountryName=(subCountryName)?[NSString stringWithUTF8String:subCountryName]: #"";
sbCountryObj.subCountryComment=(subCountryComment)?[NSString stringWithUTF8String:subCountryComment]: #"";
sbCountryObj.image=(image)?[NSString stringWithUTF8String:image]: #"";
[subCountiresArr addObject:sbCountryObj];
}
sqlite3_finalize(statement);
sqlite3_close(database);
}
else
{
NSLog(#"%s: prepare failed: %s", __FUNCTION__, sqlite3_errmsg(database));
}
}
else
{
//[self dbConnectionError];
}
return subCountiresArr;
}
You're specifying the database path as userDB in your SQL, but that's not the name of the database file. That is, the name of the variable that has the full path name in it, but you presumably actually have to build your SQL with that filename. For example:
NSString *sql = [NSString stringWithFormat:#"attach database '%#' as usdb", userDB];
const char *sqlAttachedDatabase = [sql UTF8String];
Execute that. Then, as a separate statement, you can execute your SELECT SQL that uses the usdb alias. And when you're done, detach the database.
Also, I notice that you're checking to see if the result is SQLITE_OK (which is good). But you're not showing any diagnostic information if it's not. For example, your SQL is wrong, but you're not showing a meaningful error message. Thus, if your sqlite3_prepare_v2 fails to return SQLITE_OK, you should:
NSLog(#"%s: prepare failed: %s", __FUNCTION__, sqlite3_errmsg(database));
If you do this when you have an error, you'll be able to figure out what's wrong. Without that, you're flying blind.
A working example, where my "author" database is in the bundle, and my "book" database is in Documents:
int rc;
NSString *docsPath = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)[0];
NSString *bookFilename = [docsPath stringByAppendingPathComponent:#"book.sqlite"];
NSString *authorFilename = [[NSBundle mainBundle] pathForResource:#"author" ofType:#"sqlite"];
sqlite3 *database;
if ((rc = sqlite3_open([authorFilename UTF8String], &database)) != SQLITE_OK)
{
NSLog(#"%s: open failed: %s (%d)", __FUNCTION__, sqlite3_errmsg(database), rc);
return;
}
NSString *sql = [NSString stringWithFormat:#"attach database '%#' as userdb;", bookFilename];
if ((rc = sqlite3_exec(database, [sql UTF8String], NULL, NULL, NULL)) != SQLITE_OK)
NSLog(#"%s: attach failed: %s (%d)", __FUNCTION__, sqlite3_errmsg(database), rc);
sqlite3_stmt *statement;
sql = #"select book.*, author.* from userdb.book inner join author on author_id = book_author_id;";
if ((rc = sqlite3_prepare_v2(database, [sql UTF8String], -1, &statement, NULL)) != SQLITE_OK)
NSLog(#"%s: prepare failed: %s (%d)", __FUNCTION__, sqlite3_errmsg(database), rc);
while ((rc = sqlite3_step(statement)) == SQLITE_ROW)
{
// do whatever you want row by row
NSLog(#"Row");
}
if (rc != SQLITE_DONE)
NSLog(#"%s: step failed: %s (%d)", __FUNCTION__, sqlite3_errmsg(database), rc);
sqlite3_finalize(statement);
sql = #"detach database userdb;";
if ((rc = sqlite3_exec(database, [sql UTF8String], NULL, NULL, NULL)) != SQLITE_OK)
NSLog(#"%s: detach failed: %s (%d)", __FUNCTION__, sqlite3_errmsg(database), rc);
sqlite3_close(database);
You should do the following:
Run SQL "attach database 'full db path' as usdb", where "full db path" is full path to database file
Prepare and execute SELECT statement (remove "attach database ..." from it)
Detach database when it's not needed "detach database 'full db path'"
Related
I'm insert data into sqlite database and I've seen NSLog(#"DONE") on my console result, but I don't see the data update in my sqlite database file. Pls help me !!!
Here my code to save data:
- (void)saveData:(NSString *)_Id
{
sqlite3_stmt *statement;
NSString *_databasePath = [[[NSBundle mainBundle] resourcePath ]stringByAppendingPathComponent:#"data.db"];
const char *dbpath = [_databasePath UTF8String];
if (sqlite3_open(dbpath, &db) == SQLITE_OK)
{
NSString *insertSQL = [NSString stringWithFormat:
#"INSERT INTO MyTable (id) VALUES (\"%#\")", _Id];
const char *insert_stmt = [insertSQL UTF8String];
sqlite3_prepare_v2(db, insert_stmt,
-1, &statement, NULL);
if (sqlite3_step(statement) == SQLITE_DONE)
{
NSLog(#"DONE");
} else {
NSLog(#"Failed to add contact");
}
sqlite3_finalize(statement);
sqlite3_close(db);
}
}
You are opening the database in your bundle. The bundle is read-only on the device. You must copy the database to your Documents folder (if it doesn't exist there already) and open it from there.
Also be aware that you're dealing with multiple copies of the database (the one in your project, the one in the bundle and now the one in the device/simulator's Documents folder). Make sure you're checking for the inserted record in the correct database (the one in Documents)
As an aside, you should also check to see that sqlite3_prepare_v2 returned SQLITE_OK and if not, log sqlite3_errmsg.
You should also use ? placeholder in your SQL and bind values using sqlite3_bind_text (or, if it's possibly nil, sqlite_bind_null):
- (void)saveData:(NSString *)_Id
{
sqlite3_stmt *statement;
NSString *bundlePath = [[[NSBundle mainBundle] resourcePath ] stringByAppendingPathComponent:#"data.db"];
NSString *documentsFolder = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)[0];
NSString *documentsPath = [documentsFolder stringByAppendingPathComponent:#"data.db"];
NSFileManager *fileManager = [NSFileManager defaultManager];
if (![fileManager fileExistsAtPath:documentsPath isDirectory:NO]) {
NSError *error;
if (![fileManager copyItemAtPath:bundlePath toPath:documentsPath error:&error]) {
NSLog(#"database copy failed: %#", error);
}
}
const char *dbpath = [documentsPath UTF8String];
if (sqlite3_open(dbpath, &db) == SQLITE_OK) {
const char *insertSql = "INSERT INTO MyTable (id) VALUES (?)";
if (sqlite3_prepare_v2(db, insertSql, -1, &statement, NULL) != SQLITE_OK) {
NSLog(#"prepare error: %s", sqlite3_errmsg(db));
}
// bind a value to the ? placeholder in the SQL
if (_Id) {
if (sqlite3_bind_text(statement, 1, [_Id UTF8String], -1, SQLITE_TRANSIENT) != SQLITE_OK) {
NSLog(#"bind text error: %s", sqlite3_errmsg(db));
}
} else {
if (sqlite3_bind_null(statement, 1) != SQLITE_OK) {
NSLog(#"bind null error: %s", sqlite3_errmsg(db));
}
}
if (sqlite3_step(statement) == SQLITE_DONE) {
NSLog(#"DONE");
} else {
NSLog(#"Failed to add contact: %s", sqlite3_errmsg(db));
}
sqlite3_finalize(statement);
sqlite3_close(db);
}
}
Most people move that "if database doesn't exist in documents, then copy it from the bundle and open it from there" logic inside a dedicated openDatabase method, but hopefully this illustrates the idea.
On the first implemetation file, all steps
- (void) readCitiesFromDatabase {
databaseName = #"123.sqlite";
NSArray *documentPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDir = [documentPaths objectAtIndex:0];
databasePath = [documentsDir stringByAppendingPathComponent:databaseName];
// Setup the database object
sqlite3 *database;
// Setup the SQL Statement and compile it for faster access
NSString *querySQL = [NSString stringWithFormat:#"SELECT City_Name, City_Picture, City_Id FROM CITIES, COUNTRIES WHERE CITIES.Country_Id=COUNTRIES.Country_Id AND COUNTRIES.Country_Id = '%#'", self.countryID];
const char *sqlStatement = [querySQL UTF8String];
sqlite3_stmt *compiledStatement;
// Init the countries Array
self.cities = [[NSMutableArray alloc] init];
// Open the database from the users filessytem
if(sqlite3_open([databasePath UTF8String], &database) == SQLITE_OK) {
NSLog(#"success");
if(sqlite3_prepare_v2(database, sqlStatement, -1, &compiledStatement, NULL) == SQLITE_OK) {
NSLog(#"success");
while(sqlite3_step(compiledStatement) == SQLITE_ROW)
{
NSLog(#"success");
// Read the data from the result row
char *temp_cName = (char *)sqlite3_column_text(compiledStatement, 0);
NSString *cName = temp_cName == NULL ? nil : [[NSString alloc] initWithUTF8String:temp_cName];
char *temp_cPicture = (char *)sqlite3_column_text(compiledStatement, 1);
NSString *cPicture = temp_cPicture == NULL ? nil : [[NSString alloc] initWithUTF8String:temp_cPicture];
char *temp_cId = (char *)sqlite3_column_text(compiledStatement, 2);
NSString *cId = temp_cId == NULL ? nil : [[NSString alloc] initWithUTF8String:temp_cPicture];
NSMutableDictionary *city = [[NSMutableDictionary alloc] init];
[city setObject:cName forKey:#"City_Name"];
[city setObject:cPicture forKey:#"City_Picture"];
[city setObject:cId forKey:#"City_Id"];
[self.cities addObject:city];
}
}
// Release the compiled statement from memory
sqlite3_finalize(compiledStatement);
}
sqlite3_close(database);
}
Now I got cities list. When I select a city, I could not see city info.
This is from second implementation.
- (void) readCityInfoFromDatabase:(NSString *)querySQL
{
databaseName = #"123.sqlite";
NSArray *documentPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDir = [documentPaths objectAtIndex:0];
databasePath = [documentsDir stringByAppendingPathComponent:databaseName];
// Setup the database object
sqlite3 *database;
// Setup the SQL Statement and compile it for faster access
const char *sqlStatement = [querySQL UTF8String];
sqlite3_stmt *compiledStatement;
// Open the database from the users filessytem
if(sqlite3_open([databasePath UTF8String], &database) == SQLITE_OK) {
NSLog(#"success");
if(sqlite3_prepare_v2(database, sqlStatement, -1, &compiledStatement, NULL) == SQLITE_OK) {
NSLog(#"success");
if (sqlite3_step(compiledStatement) == SQLITE_ROW)
{
NSLog(#"success");
char *temp_content = (char *)sqlite3_column_text(compiledStatement, 0);
[self.cityTextView setText:temp_content == NULL ? nil : [[NSString alloc] initWithUTF8String:temp_content]];
}
}
sqlite3_finalize(compiledStatement);
}
sqlite3_close(database);
}
The first two steps are success but,
if (sqlite3_step(compiledStatement) == SQLITE_ROW)
{
NSLog(#"success");
I couldn't see success on this step.
Please help.
You really should be saving the result of sqlite3_step() and checking to see if it is:
SQLITE_ROW = retrieved row of data
SQLITE_DONE = no (more) data to retrieve
Other = some error occurred
On the basis of what you shared, though, there is a good chance that you simply received SQLITE_DONE because there was nothing found. You could get that if there was a mistake in the SQL (e.g. bad join, incorrect WHERE clause, etc.). It's hard to say without seeing the SQL used by readCityInfoFromDatabase and some representative data from the database.
By the way, not only for sqlite3_step(), but rather for all of your sqlite3_xxx() calls, if you receive an error, you should be logging sqlite3_errmsg(). Right now, if there was an error, you'd have to guess what the source of the problem was.
hi i'm getting stuck with some code. i have a file catalog.db and a class that let me work with it. When i try to retrieve datas from the db it seems like it's empty. With several nslog i can see that it connect and enter the database, i can see it enter in it but then it won't get any value from it.
i tried to see if the query was wrong with an external DB manager software and the query works fine...
this is my class
#import "DBAccess.h"
sqlite3* database;
#implementation DBAccess
-(id)init{
self = [super init];
if (self){
[self initializeDatabase];
}
return self;
}
-(void)initializeDatabase{
NSString *path = [[NSBundle mainBundle]pathForResource:#"catalog" ofType:#"db"];
if (sqlite3_open([path UTF8String], &database) == SQLITE_OK) { NSLog(#"Opening Database"); }
else {
sqlite3_close(database);
NSAssert1(0, #"FAILED to open database '%s'", sqlite3_errmsg(database));
}
}
-(void)closeDatabase{
if (sqlite3_close(database) != SQLITE_OK){
NSAssert1(0, #"ERROR to close databse: '%s'", sqlite3_errmsg(database));
}
}
-(NSMutableArray *)getAllProduct{
NSMutableArray *products = [[NSMutableArray alloc]init];
const char *sql = "SELECT product.ID,product.Name, Manufacturer.name, product.details,product.price, product.quantityOnHand,country.country,product.image FROM product,manufacturer,country WHERE manufacturer.manufacturerID = product.manufacturerID and product.countryOfOriginID = country.countryID";
sqlite3_stmt *statement;
int sqlResult = sqlite3_prepare_v2(database, sql, -1, &statement, NULL);
NSLog(#"sqlResult: %d", sqlResult);
if (sqlResult == SQLITE_OK){
NSLog(#"sql step statement: %d",sqlite3_step(statement));
NSLog(#"QUERY DONE");
while (sqlite3_step(statement) == SQLITE_ROW){
NSLog(#"TEST");
Product *product = [[Product alloc]init];
char *name = (char *)sqlite3_column_text(statement, 1);
NSLog(#"n %s",name);
char *manufacturer = (char *)sqlite3_column_text(statement, 2);
NSLog(#"m %s", manufacturer);
char *details = (char *)sqlite3_column_text(statement, 3);
NSLog(#"d %s", details);
char *countryoforigin = (char *)sqlite3_column_text(statement, 6);
NSLog(#"%s", countryoforigin);
char *image = (char *)sqlite3_column_text(statement, 7);
NSLog(#"%s", image);
product.ID = sqlite3_column_text(statement, 0);
product.name = (name)?[NSString stringWithUTF8String:name]:#"";
product.manufacturer = (manufacturer)?[NSString stringWithUTF8String:manufacturer]:#"";
product.details = (details)?[NSString stringWithUTF8String:details]:#"";
product.price = sqlite3_column_double (statement, 4);
product.quantity = sqlite3_column_int(statement, 5);
product.countryOfOrigin = (countryoforigin)?[NSString stringWithUTF8String:countryoforigin]:#"";
product.image = (image)?[NSString stringWithUTF8String:image]:#"";
[products addObject:product];
}
sqlite3_finalize(statement);
}
else {
NSLog(#"Problem with database %d",sqlResult);
}
return products;
}
#end
this is what i get in my console
2013-08-14 12:38:58.505 Catalog[1642:c07] Opening Database
2013-08-14 12:38:58.508 Catalog[1642:c07] sqlResult: 0
2013-08-14 12:38:58.509 Catalog[1642:c07] sql step statement: 101
2013-08-14 12:38:58.509 Catalog[1642:c07] QUERY DONE
2013-08-14 12:38:58.510 Catalog[1642:c07] ()
what can be my problem? thanks
Here
NSLog(#"sql step statement: %d",sqlite3_step(statement));
you fetch already the first row (without using the result).
1)Copy the database to your documents directory...
-(void) checkAndCreateDatabase{
// Check if the SQL database has already been saved to the users phone, if not then copy it over
NSArray *documentPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDir = [documentPaths objectAtIndex:0];
NSString *databasePath = [documentsDir stringByAppendingPathComponent:#"test.sqlite"];
BOOL success;
// Create a FileManager object, we will use this to check the status
// of the database and to copy it over if required
NSFileManager *fileManager = [NSFileManager defaultManager];
// Check if the database has already been created in the users filesystem
success = [fileManager fileExistsAtPath:databasePath];
// If the database already exists then return without doing anything
if(success) return;
// If not then proceed to copy the database from the application to the users filesystem
// Get the path to the database in the application package
NSString *databasePathFromApp = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:#"test.sqlite"];
// Copy the database from the package to the users filesystem
[fileManager copyItemAtPath:databasePathFromApp toPath:databasePath error:nil];
}
2)Then talk to database in this way.
-(void)sqliteTransaction
{
sqlite3 *database;
NSArray *documentPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDir = [documentPaths objectAtIndex:0];
NSString *databasePath = [documentsDir stringByAppendingPathComponent:#"test.sqlite"];
// Init the animals Array
// Open the database from the users filessytem
if(sqlite3_open([databasePath UTF8String], &database) == SQLITE_OK) {
// Setup the SQL Statement and compile it for faster access
const char *sqlStatement = "select * from me";
sqlite3_stmt *compiledStatement;
if(sqlite3_prepare_v2(database, sqlStatement, -1, &compiledStatement, NULL) == SQLITE_OK) {
// Loop through the results and add them to the feeds array
while(sqlite3_step(compiledStatement) == SQLITE_ROW) {
// Read the data from the result row
NSString *aName = [NSString stringWithUTF8String:(char *)sqlite3_column_text(compiledStatement, 1)];
NSLog(#"%#",aName);
// Create a new animal object with the data from the database
}
}
// Release the compiled statement from memory
sqlite3_finalize(compiledStatement);
}
sqlite3_close(database);
}
Try like this, before going to SELECT make sure the table is properly connected for selection with the open query like this
sqlite3_open(dbpath, &ProDB)
After that execute your selection. See this below sample code. Hope it will help
ex:
NSMutableArray *sessionDetails = [NSMutableArray array];
NSString *docsDir;
NSArray *dirPaths;
dirPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
docsDir = [dirPaths objectAtIndex:0];
NSString *databasePath = [[NSString alloc] initWithString: [docsDir stringByAppendingPathComponent: #"cPro.db"]];
const char *dbpath = [databasePath UTF8String];
sqlite3_stmt *statement;
if (sqlite3_open(dbpath, &ProDB) == SQLITE_OK)
{
NSString *querySQL = [NSString stringWithFormat: #"SELECT * FROM USER_SESSION_INFO"];
NSLog(#"query: %#",querySQL);
const char *query_stmt = [querySQL UTF8String];
if (sqlite3_prepare_v2(ProDB, query_stmt, -1, &statement, NULL) == SQLITE_OK)
{
while(sqlite3_step(statement) == SQLITE_ROW)
{
// Your functionality.
}
}
}
i tried the method you guys suggested but i still get the same problem.
i think i found out what's causing it.
i changed my query with this:
const char *sql = "SELECT product.ID,product.Name, product.details,product.price, product.quantityOnHand,product.image FROM Product";
and this way it works... so it looks like i have trouble reading other tables...
the moment i add another table it stop working. but that's weird cause with external db manager software the query works just fine
this is what i am doing in header
static sqlite3 *database = nil;
static sqlite3_stmt *deleteStmt = nil;
#implementation SQLAppDelegate
#synthesize window;
#synthesize navigationController;
#synthesize coffeeArray;
this is what i am using for deleting raw
- (void) removeCoffee:(NSNumber *)coffeeObj {
NSLog(#"coffeeObj%#",coffeeObj);
int myInteger = [coffeeObj integerValue];
NSLog(#"myInteger%d",myInteger);
// print this myInteger0
NSLog(#"%#",coffeeArray);
//print object
if (sqlite3_open([self getDBPath], &database) == SQLITE_OK)
{
NSLog(#"myInteger%#",[self getDBPath]);
NSString *sql = [NSString stringWithFormat: #"delete from Coffee where CoffeeID =%d",myInteger];
const char *del_stmt = [sql UTF8String];
NSLog(#"%#",del_stmt); // getting print
// print this delete from Coffee where CoffeeID =0.
sqlite3_prepare_v2(database, del_stmt, -1, & deleteStmt, NULL);
NSLog(#"sqlite3_step(deleteStmt) == SQLITE_DONE%#",sqlite3_step(deleteStmt) == SQLITE_DONE);
// this print null
if (sqlite3_step(deleteStmt) == SQLITE_DONE)
{
//NSLog(#"hi") this is not getting print
} else {
//NSLog(#"hi") this is getting print
}
sqlite3_finalize(deleteStmt);
sqlite3_close(database);
[coffeeArray removeObjectAtIndex:myInteger];
NSLog(#"%#",coffeeArray);
// object is deleted
}
}
my table is like below
table name = Coffee
CoffeeID(INTEGER)=0
CoffeeName(VARCHAR)=Latte
Price(REAL)=2.99
where thing runs perfectly object get deleted from array and thats why its not appearing on table cell. but its not getting deleted from database table thats why it when i launch app again then it shows again please help what i am doing wrong.
Before start deleting the object just conform once the database is opened properly or not. Just try like this.
//Setting path
NSArray *dirPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *docsDir = [dirPaths objectAtIndex:0];
databasePath = [[NSString alloc] initWithString: [docsDir stringByAppendingPathComponent: #"database.db"]];
const char *dbpath=[databasePath UTF8String];
if (sqlite3_open(dbpath, &database) == SQLITE_OK)
{
NSString *sql = [NSString stringWithFormat: #"delete from Coffee where CoffeeID =%d",myInteger];
const char *del_stmt = [sql UTF8String];
sqlite3_prepare_v2(database, del_stmt, -1, & deleteStmt, NULL);
if (sqlite3_step(deleteStmt) == SQLITE_DONE)
{
} else {
}
sqlite3_finalize(deleteStmt);
sqlite3_close(database);
[coffeeArray removeObjectAtIndex:myInteger];
NSLog(#"%#",coffeeArray);
// object is deleted
}
if(sqlite3_open([[self filepath] UTF8String], &db) == SQLITE_OK)
{
Deletestatement = nil;
if(Deletestatement == nil)
{
const char *sql = "delete from Sqlitemanager2;";
if(sqlite3_prepare_v2(db, sql, -1, &Deletestatement, NULL) != SQLITE_OK)
NSAssert1(0, #"Error while creating delete statement. '%s'", sqlite3_errmsg(db));
}
if (SQLITE_DONE != sqlite3_step(Deletestatement)) //prathibha for problem in if
NSAssert1(0, #"Error while deleting. '%s'", sqlite3_errmsg(db));
sqlite3_finalize(Deletestatement);
}
I hope this will help you.
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.