Unable to delete row data in my table view from sqlite - ios

I am trying to delete the data from my table view.The data is coming from the database.
if (editingStyle == UITableViewCellEditingStyleDelete) {
DetailData *datatoDelete;//=[DetailData new];
datatoDelete= dataArray[indexPath.row];
NSLog(#"ID at selected row is %#",datatoDelete.ID);
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:
#"MYDat.db"]];
const char *dbpath = [databasePath UTF8String];
sqlite3_stmt *statement;
if (sqlite3_open(dbpath, &myDatabase) == SQLITE_OK)
{
NSString *querySQL = [NSString stringWithFormat:#"DELETE FROM ABC WHERE ID=%#",datatoDelete.ID];
// i tried ID='%#' too
const char *query_stmt = [querySQL UTF8String];
if (sqlite3_prepare_v2(myDatabase, query_stmt, -1, &statement, NULL) == SQLITE_OK)
{
NSLog(#"statement deleted successfully"); // i am seeing this statement when i click delete
}
sqlite3_finalize(statement);
sqlite3_close(myDatabase);
}
// [dataArray removeObjectAtIndex:indexPath.row];
[tableView reloadData];
}
Here when I click on delete, i am getting "the statement data deleted successfully" but,when I check the database file after the delete operation, the data still exists there.Could anyone tell me whats wrong in here?

The sqlite3_prepare_v2 only prepares a statement, you need to use sqlite3_step for executing it.
if (sqlite3_prepare_v2(myDatabase, query_stmt, -1, &statement, NULL) == SQLITE_OK)
{
if(sqlite3_step(statement) == SQLITE_DONE)
{
NSLog(#"statement deleted successfully");
}
}
For referece:
sqlite_step
Evaluate An SQL Statement

Related

IOS Sqlite3 Passing Opened database to a method

Using php for an example:
$conn = new mysqli('localhost', 'xxx', '123456', 'xxx');
Just define $conn once, I can pass $conn to all other methods, so that i don't need to repeat the connection again when I run another query, and it's a lot faster.
function example($conn) {
// do some db stuff here
}
Can I do the same thing in IOS sqlite3? Many thanks for helping.
- (void) syncScale {
// 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:#"ALDI.db"]];
const char *dbpath = [databasePath UTF8String];
sqlite3_stmt *statement;
NSString *postSetting ;
postSetting = [NSString stringWithFormat:#"scaleData={\"scaleDB\":["];
if (sqlite3_open(dbpath, &contactDB) == SQLITE_OK)
{
NSString *querySQL = #"SELECT * From Table1";
const char *query_stmt = [querySQL UTF8String];
if (sqlite3_prepare_v2(contactDB, query_stmt, -1, &statement, NULL) == SQLITE_OK)
{
while (sqlite3_step(statement) == SQLITE_ROW)
{
// do something here
}
sqlite3_finalize(statement);
} else {
NSLog(#"Steps Data not found");
}
sqlite3_close(contactDB);
}
}
What I usually do, is that keep the opening of database in separate block/function with a boolean return ,rather finalize and rest the sqlite statement; Since the opening of database is made of almost static contents, the function doesn't need any parameters

if (sqlite3_step(compiledStatement) == SQLITE_ROW) is fail

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.

(Objective C) Save changes in sqlite database

I'm creating an app for my school project that has to write data to my sqlite database. It works, as long as the app is running active but as soon as the app closes, my added data is gone and when I want to read this data this will not work off course. I included both my loadData and saveData methods. The two database paths are the same in both functions so it's not that I'm writing my data elsewhere. I really can't find the solution or the problem. I even get the insert success in my output, so the insert is successful.
- (void) saveData:(id)sender{
NSString *sqldb = [[NSBundle mainBundle] pathForResource:#"PXLate" ofType:#"sqlite3"];
sqlite3_stmt *stmt;
NSString *queryInsert = #"INSERT INTO assignments (name, lesson, dueDate, notification, start, at) VALUES ('abc','abc', 'abc', 1, 'abc', 'abc')";
NSLog(#"%#",sqldb);
NSLog(#"%#",queryInsert);
if(sqlite3_open([sqldb UTF8String], &_PXLate) == SQLITE_OK)
{
sqlite3_prepare_v2(_PXLate, [queryInsert UTF8String], -1, &stmt, NULL);
if(sqlite3_step(stmt)==SQLITE_DONE)
{
NSLog(#"insert success");
}
else
{
NSLog(#"insert un success");
NSAssert1(0, #"Error: failed to prepare statement with message '%s'.", sqlite3_errmsg(_PXLate));
}
int success=sqlite3_step(stmt);
if (success == SQLITE_ERROR)
{
NSAssert1(0, #"Error: failed to insert into the database with message '%s'.", sqlite3_errmsg(_PXLate));
//[_PXLate save:&error];
} sqlite3_finalize(stmt);
}
sqlite3_close(_PXLate);
}
and my loadData function
- (void) loadData:(id)sender
{
//path for database
NSString *sqldb = [[NSBundle mainBundle] pathForResource:#"PXLate" ofType:#"sqlite3"];
//check if present
NSFileManager*fm=[NSFileManager defaultManager];
NSLog(#"path: %#", sqldb);
const char *dbpath = [sqldb UTF8String];
sqlite3_stmt *statement;
if (sqlite3_open(dbpath, &_PXLate) == SQLITE_OK)
{
NSString *querySQL = [NSString stringWithFormat: #"SELECT * FROM assignments WHERE name='abc'", _label.text];
const char *query_stmt = [querySQL UTF8String];
NSLog(#"name");
NSLog(querySQL);
int response = sqlite3_prepare_v2(_PXLate, query_stmt, -1, &statement, NULL);
NSLog(#"response %d", response);
if (response == SQLITE_OK)
{
NSLog(#"name");
if (sqlite3_step(statement) == SQLITE_ROW)
{
NSString *namefield = [[NSString alloc]
initWithUTF8String:
(const char *) sqlite3_column_text(
statement, 0)];
NSLog(#"name:%#", namefield);
_label.text = namefield;
} else {
_label.text = #"Match not found";
}
sqlite3_finalize(statement);
}
sqlite3_close(_PXLate);
}
}
You have to copy your sqlite to the documents directory and then work with that. Example:
self.databaseName = #"databasename.sqlite";
// Get the path to the documents directory and append the databaseName
NSArray *documentPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDir = [documentPaths objectAtIndex:0];
self.databasePath = [[NSString alloc]init];
self.databasePath = [documentsDir stringByAppendingPathComponent:self.databaseName];
[self checkAndCreateDatabase];
And the create method:
-(void)checkAndCreateDatabase
{
NSFileManager *fileManager = [NSFileManager defaultManager];
NSString *databasePathFromApp = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:self.databaseName];
[fileManager copyItemAtPath:databasePathFromApp toPath:self.databasePath error:nil];
}
A couple of observations:
As Retterdesdialogs said, you should
Check for existence of database in Documents;
If not there, copy from bundle to Documents; and
Open database from Documents.
You should not open database from bundle, because on the device that folder is read-only.
In your INSERT statement you are not checking the response of sqlite3_prepare_v2, which is a very common source of errors. If this is not SQLITE_OK, you should immediately log sqlite3_errmsg, before you call sqlite3_step.
You are performing sqlite3_step twice in the INSERT statement.
In loadData, you are not logging sqlite3_errmsg if sqlite3_prepare_v2 failed. Always look at sqlite3_errmsg upon any error.

Objective-c sql error - error with statement look like empty result

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

Issue in deleting raw from table sqlite

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.

Resources