Help please :-)
Following code is supposed to delete a record. It seems to execute OK, no error message and the NSLog shows "Record Deleted" message. However the record is not deleted. I have used Terminal to check and indeed the deleted record is still there. The puzzling part is that I have very similar code to add and count records and they all seem to work... I am not an SQL expert, so I am hoping that an expert in this crowd can see the error.
Thanks
(void) deleteRecord
{
const char *dbpath = [databasePath UTF8String];
sqlite3_stmt *statement;
if (sqlite3_open(dbpath, &wfDataBase) == SQLITE_OK)
{
NSLog(#"About to Delete Record %d",currentID);
NSString *querySQL = [NSString stringWithFormat: #"DELETE from wfDataBase WHERE ID = %d", currentID];
const char *query_stmt = [querySQL UTF8String];
if (sqlite3_prepare_v2(wfDataBase, query_stmt, -1, &statement, NULL) == SQLITE_OK)
l_status.text = #"Record Deleted";
else
l_status.text = #"Can't Delete";
sqlite3_finalize(statement);
sqlite3_close(wfDataBase);
}
}
Are you sure you have evaluated (sqlite3_step(statement )) the compiled statement (sqlite3_prepare_v2(wfDataBase, query_stmt, -1, &statement, NULL)) before destroying it (sqlite3_finalize(statement))?
Note: I'm not an expert on SQLite (indeed I don't know anything about SQLite) but I guess this is the cause of the problem.
Related
I'm having two crashes show up in my logs using the following code to insert into my SQLite DB - the code works perfectly most of the time however clearly there is a something wrong that's causing the crash.
It crashes on either sqlite3_last_insert_rowid or sqlite3_close with EXC_BAD_ACCESS (I hold a reference to the SMSDatabase and it's in a singleton not sure why it would be deallocated) and SIGABRT (memory issue?)
- (NSInteger)query:(NSString *)query {
NSInteger lastRowID = 0;
if (sqlite3_open([self.databasePath UTF8String], &smsDatabase) == SQLITE_OK)
{
sqlite3_stmt *statement = nil;
const char *sql = [query UTF8String];
if (sqlite3_prepare_v2(smsDatabase, sql, -1, &statement, NULL) == SQLITE_OK) {
if (sqlite3_step(statement) == SQLITE_DONE)
{
lastRowID = sqlite3_last_insert_rowid(smsDatabase);
}
}
sqlite3_finalize(statement);
}
sqlite3_close(smsDatabase);
return lastRowID;
}
Where am I going wrong?
sqlite3_close(smsDatabase); - isn't this outside your if statement, which means you are closing a database which may have never been opened ?
I have a problem with sqlite, when i select a single row from table and then check sqlite3_step(statement) == SQLITE_ROW both values are different and not getting inside while statement.
This is the code:
if (sqlite3_prepare_v2(db, query_stmt, -1, &statement, NULL) == SQLITE_OK)
{
//NSLog(#"working777.............%d",sqlite3_step(statement));
while (sqlite3_step(statement) == SQLITE_ROW)
{
NSLog(#"working888.............%d",SQLITE_ROW);
NSString *addressField = [[NSString alloc] initWithUTF8String: (const char *) sqlite3_column_text(statement, 0)];
NSString *phoneField = [[NSString alloc] initWithUTF8String:(const char *)sqlite3_column_text(statement, 1)];
NSLog(#"............statement...........addressField %#, phoneField %#",addressField,phoneField);
}
sqlite3_finalize(statement);
}
sqlite3_close(db);
}
The proper way to create such a query would be like this:
NSString *querySQL = #"SELECT * FROM Major_Events WHERE temple_id = ?";
Then prepare the statement. I assume query_stmt is the char * value from querySQL.
Once the statement is prepared you then need to bind the value.
sqlite3_bind_int(statement, 1, temp_id); // bind is 1-based
Of course temp_id needs to be an int value and not a string. There are various sqlite3_bind_xxx statements for different data types. Use the appropriate one.
Once all of the query parameters are bound, you can execute the query using sqlite3_step.
The nice thing about this approach over string formats is that strings get properly escape and put in quotes for you. It's much harder to mess up and it makes your queries much safer against SQL injection attacks.
For many records:-
if (sqlite3_open([[self getDBPath] UTF8String], &database) == SQLITE_OK) {
const char *sql = "select * from Place";
sqlite3_stmt *selectstmt;
if(sqlite3_prepare_v2(database, sql, -1, &selectstmt, NULL) == SQLITE_OK) {
while(sqlite3_step(selectstmt) == SQLITE_ROW) {
}
sqlite3_finalize(selectstmt);
sqlite3_close(database);
}
}
else
{
sqlite3_close(database);
}
If you want a single record then change while to if
if(sqlite3_step(selectstmt) == SQLITE_ROW) {
rest everything will be same
I hope it helps and if your while loop is not getting executed then it means there is some problem with your query.You need to check that also.
I'm so trying to connect the sqlite but can't. Can someone help me? I don't see any error here at all and I've searched high and low for this problem on google and here but I can't find any way to fix this.
I'm following the tutorial here
Do help me, I'm going crazy over this error. =(
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
sqlite3 *contactDB; //declare pointer to database structurery
const char *dbPath = [databasePath UTF8String]; //convert NSString to UTF8String
//open database file. TRUE = success, FALSE = failed
if (sqlite3_open(dbPath, &contactDB)== SQLITE_OK){
NSLog(#"Opened");
sqlite3_stmt *statement;
NSString *querySQL = #"SELECT address, phone FROM contacts";
const char *query_stmt = [querySQL UTF8String];
if (sqlite3_prepare_v2(contactDB, query_stmt, 1, &statement, NULL) == SQLITE_OK) {
NSLog(#"Statement is OK");
}else{
NSLog(#"Statement FAILED");
}
}else{
NSLog(#"Failed");
}
The log only reads "Opened" then "Statement FAILED"
This is how I do it. (Compiled piece of my database class)
Shows you the sql error too.
sqlite3 *_database;
sqlite3_open([databasePath UTF8String], &_database);
NSString *sqlStatement = #"SELECT address, phone FROM contacts";
const char *sql = [sqlStatement UTF8String];
static sqlite3_stmt *compiledStatement;
int result = sqlite3_prepare_v2(_database, sql, -1, &compiledStatement, NULL);
if(result != SQLITE_OK) {
NSLog(#"Prepare-error #%i: %s", result, sqlite3_errmsg(_database));
}
result = sqlite3_step(compiledStatement);
if (result != SQLITE_DONE) {
NSLog(#"Step-error #%i for '%#': %s", result, sqlStatement, sqlite3_errmsg(_database));
}
sqlite3_finalize(compiledStatement);
The error is in this line of code.
if (sqlite3_prepare_v2(contactDB, query_stmt, 1, &statement, NULL) == SQLITE_OK) {
The 1 is wrong. From the SQLite docs:
int sqlite3_prepare_v2(
sqlite3 *db, /* Database handle */
const char *zSql, /* SQL statement, UTF-8 encoded */
int nByte, /* Maximum length of zSql in bytes. */
sqlite3_stmt **ppStmt, /* OUT: Statement handle */
const char **pzTail /* OUT: Pointer to unused portion of zSql */
);
If the nByte argument is less than zero, then zSql is read up to the first zero
terminator. If nByte is non-negative, then it is the maximum number of bytes
read from zSql.
So you are forcing SQLite to only read the first byte from the statement. Of course this is invalid.
Make sure these points you have done in your project.
Verify the file is listed under "Copy Bundle Resources" under your Target's "Build Phases" and NOT under "Copy Files" with a custom destination or sub-path.
Make sure you don't have any path conflicts with your sqlite file.I mean document directory/database path/ are correct.
And I have implemented sqlite query like
SELECT * FROM someTable WHERE status LIKE 'someString' AND BankName LIKE 'someString'
Instead of
SELECT * FROM someTable WHERE status='someString' AND BankName='someString'
Make sure you have not included your sqlite file in any other application
Make sure you don't have duplicate sqlite files with same path.
This is worked for me after lot of struggle, I hope it helps some one. Please up vote if it helps.
I have this simple function in my application :
-(NSMutableArray *)SelectProductID:(NSMutableArray *)arr
{
NSLog(#"----------------");
sqlite3_stmt *statement;
NSMutableArray *arrPordID = [[NSMutableArray alloc]init];
#try
{
//Get productID
for(NSString *strSubProductID in arr)
{
NSString *s = [NSString stringWithFormat:#"SELECT ProductID FROM SubProducttable where SubProductID=%#",strSubProductID];
const char *sql = [s cStringUsingEncoding:NSASCIIStringEncoding];
if (sqlite3_prepare_v2(database, [s cStringUsingEncoding:NSUTF8StringEncoding], -1, &statement, NULL) == SQLITE_OK) {
while (sqlite3_step(statement) == SQLITE_ROW){
char *dbString;
dbString = (char *)sqlite3_column_text(statement, 0);
NSString *pID = (dbString) ? [NSString stringWithUTF8String:dbString] : #"";
[arrPordID addObject:pID];
}
}
}
}
#catch (NSException *exception) {
#throw exception;
}
#finally {
sqlite3_finalize(statement);
}
return arrPordID;
}
I am encountering a strange problem here. When application reaches while (sqlite3_step(statement) == SQLITE_ROW){, loop is never entered. I don't know why. I executed the same query in SQLite manager (when application is not running). And I get result as a single one. The result I get is 2. But here I am getting nothing.
And yes, I always close the database in SQLite manager whenever I run my application. I have also cleaned the application, restarted XCode, and removed the application from simulator. But no success.
Also I saw a strange thing during debugging. While debugging, sqlite3_stmt *statement is always skipped. Is this the reason I am not getting any result?
Have you tried subproductId in single quotes?
NSString *s = [NSString stringWithFormat:#"SELECT ProductID FROM SubProducttable where SubProductID='%#'",strSubProductID];
if(sqlite3_open([databasePath UTF8String], &database) == SQLITE_OK) {
// Setup the SQL Statement and compile it for faster access
const char *sqlQuery = #"SELECT ProductID FROM SubProducttable where SubProductID=%#",strSubProductID;
sqlite3_stmt *statement;
if(sqlite3_prepare_v2(database, statement, -1, &sqlQuery, NULL) == SQLITE_OK) {
while(sqlite3_step(sqlQuery ) == SQLITE_ROW) {
// Read the data and add to your array object
}
}
// Release the compiled statement from memory
sqlite3_finalize(statement);
}
sqlite3_close(database)
I just started looking into SQLite for the iPhone SDK. I have been looking at this tutorial and I am wondering how can I find an ID and store the information in that field of the ID? (the tutorial increments an ID every time I press save).
Also, how can I loop though the whole database e.g., add all the id numbers up? Is there a command?
Not much changes in the database access in the methods. Only the SQLite query changes. It should be something on these lines.
- (NSInteger) sumOfIds
{
const char *dbpath = [databasePath UTF8String];
sqlite3_stmt *statement;
NSString *result;
if (sqlite3_open(dbpath, &contactDB) == SQLITE_OK)
{
NSString *querySQL = #"SELECT sum(id) FROM contacts";
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 *result = [[NSString alloc] initWithUTF8String:(const char *)sqlite3_column_text(statement, 0)];
}
sqlite3_finalize(statement);
}
sqlite3_close(contactDB);
}
return [result floatValue];
}