Not able to update the column value in the sqlite3 - ios

I am new to the iPhone programming and was hoping that someone would be able to help me out with a problem that I've been trying to fix for a few days now. I have created a database and a table. In my program, it contain 5 fields and I am setting two of the fields to zero. And later I am updating these fields to one for a purpose. But the problem is I am not able to set the field value to one. I will paste the code below :
NSString *querySQL = [NSString stringWithFormat: #"UPDATE TODOLIST_03 SET DELETEROW ='1' WHERE TASK=\"%#\"", cellText1];
const char *query_stmt = [querySQL UTF8String];
if (sqlite3_prepare_v2(TODOLIST_03_DB, query_stmt, -1, &statement, NULL) == SQLITE_OK)
{
if (sqlite3_step(statement) == SQLITE_ROW)
{
.........
}
}
Can anyone please tell me what is the error in the query?

try following :
const char *sqlQuery="UPDATE TODOLIST_03 SET DELETEROW ='1' WHERE TASK= ?";
if(sqlite3_prepare_v2(database, sqlQuery,-1, &queryStatement, NULL) == SQLITE_OK)
{
sqlite3_bind_text(queryStatement, 1, [cellText UTF8String], -1, NULL);
}

What path did you put database file at? It can not be wrote if you put the database file at the path same as project, you should put it in the sandbox for example NSHomeDocument where it is writeable, and you can modify code like this to track the error:
NSError *err;
if (sqlite3_prepare_v2(TODOLIST_03_DB, query_stmt, -1, &statement, &err) == SQLITE_OK)
{
if(err)
{
// NSLog error or what.
}
}

Related

Sqlite update command is not working

When i try to update a table its giving me a
error message : near "(": syntax error
Please anybody suggest me to rectify this issue.
I am updating a table when i click the save button (Bar button item) on the tool bar which is placed below.
The problem is it's always going to else statement of sqlite3_step.
I am not getting whats the exact problem for this issue and the above mentioned error.
Any suggestions would be appreciated.
Following is my update method :
if ([databaseManager didExistDatabaseInDocumentDirectory] == YES)
{
const char *dbpath = [[databaseManager getDatabasePathFromDocument] UTF8String];
sqlite3_stmt *stmt;
if (sqlite3_open(dbpath, &scanningDB) == SQLITE_OK)
{
const char *update_stmt1 = "UPDATE FILES SET (documentType,orderNumber) VALUES (?,?) WHERE ID = ?";
sqlite3_prepare_v2(scanningDB, update_stmt1, -1, &stmt, NULL);
sqlite3_bind_text(stmt, 1, [str UTF8String], -1, SQLITE_TRANSIENT);
sqlite3_bind_text(stmt, 2, [str1 UTF8String], -1, SQLITE_TRANSIENT);
sqlite3_bind_int(stmt, 3,[num intValue]);
if(sqlite3_step(stmt)==SQLITE_DONE)
{
sqlite3_reset(stmt);
NSLog(#"Record Updated Successfully");
}
else
{
NSLog(#"Could not Update Record");
NSLog(#" error message %s",sqlite3_errmsg(scanningDB));
sqlite3_finalize(stmt);
sqlite3_close(scanningDB);
return NO;
}
sqlite3_finalize(stmt);
sqlite3_close(scanningDB);
}
else
return NO;
}
else
return NO;
Please correct your query with the following.
const char *update_stmt1 = "UPDATE FILES SET documentType = ? ,orderNumber = ? WHERE ID = ?
Hope this will help you.
Your update query is wrong.
UPDATE FILES SET (documentType,orderNumber) VALUES (?,?) WHERE ID = ?
Syntax:
UPDATE table_name
SET column1 = value1, column2 = value2...., columnN = valueN
WHERE [condition];
Your query:
UPDATE FILES SET documentType =?, orderNumber =? where ID =?, documentTypeString, Yourordernumber, yourID
Sample:
- (void) update
{
if (sqlite3_open([dbPath UTF8String], &database) == SQLITE_OK)
{
if(updateStatement == nil)
{
const char *sql = "UPDATE FILES SET documentType =?, orderNumber =? where ID =?";
if(sqlite3_prepare_v2(database, sql, -1, & updateStatement, NULL) != SQLITE_OK)
NSAssert1(0, #"Error while creating update statement. '%s'", sqlite3_errmsg(database));
}
sqlite3_bind_text(documentType
, 1, [comment UTF8String], -1, SQLITE_TRANSIENT);
sqlite3_bind_text(orderNumber
, 2, [categoria UTF8String], -1, SQLITE_TRANSIENT);
sqlite3_bind_int(ID, 3, id);
if(SQLITE_DONE != sqlite3_step(updateStatement))
NSAssert1(0, #"Error while updating data. '%s'", sqlite3_errmsg(database));
else
//SQLite provides a method to get the last primary key inserted by using sqlite3_last_insert_rowid
//noteID = sqlite3_last_insert_rowid(database);
//Reset the update statement.
sqlite3_reset(updateStatement);
sqlite3_close(database);
deleteStatement = nil;
}
else
sqlite3_close(database);
}
Basic SQLite tutorial:
http://www.tutorialspoint.com/sqlite/index.htm

Drop table sqlite issue

I've been able to drop and reload tables using this same code structure, but running into an issue for this table. Essentially what my code intends to do is allow the user to delete their custom selections and restore defaults. Any insight on why I'm unable to drop table is appreciated.
EDIT: the issue was that the inital table to drop did not exist. I ended up using sqlite3_errmsg to figure that out.
- (void) dropReloadFoodlistTable{
const char *dbpath = [_databasePath UTF8String];
sqlite3_stmt *statement;
if (sqlite3_open(dbpath, &_profileDB) == SQLITE_OK)
{
NSString *querySQL = #"DROP TABLE FOODLIST";
const char *query_stmt = [querySQL UTF8String];
if (sqlite3_prepare_v2(_profileDB,
query_stmt, -1, &statement, NULL) == SQLITE_OK)
{
if (sqlite3_step(statement) == SQLITE_ROW)
{
NSLog(#"SQL Statement complete");
}
sqlite3_finalize(statement);
}
char *errMsg2;
const char *sql_stmt2 =
"CREATE TABLE IF NOT EXISTS FOODLIST (ID INTEGER PRIMARY KEY AUTOINCREMENT, CARB STRING, PROTEIN STRING, FAT STRING, FRUIT STRING, VEG STRING)";
if (sqlite3_exec(_profileDB, sql_stmt2, NULL, NULL, &errMsg2) != SQLITE_OK)
{
NSLog( #"Failed to create FOODLIST table");
}
sqlite3_close(_profileDB);
}
[self initialDataLoadFoodList];
}
This code does not execute the DROP TABLE statement.
To execute a prepared statement, you must call sqlite3_step.
You prepare the statement, but never use sqlite3_step() to actually execute it.
(reference)

Using NSString/parameters into SQLite statement iOS

I have my code below. My values _emailVaue _passwordValue and _nameValue are taken from UITextFields in my app. I was under the impression that passing these values into parameters in my SQLite code would allow me to have special characters in those values such as double quotation marks ( " ), however, if I put them in, the SQLite crashes. Is there something I'm doing wrong?
I'm aware that it's probably best to use something like FMDB, but I was hoping that there might be a quicker fix to get me through an upcoming demo.
I'd appreciate any help, thanks!
if (sqlite3_open(dbpath, &_contactDB) == SQLITE_OK)
{
NSString *insertSQL = [NSString stringWithFormat:
#"INSERT INTO CONTACTS (email, password, name) VALUES (\"%#\", \"%#\", \"%#\")",
_emailValue, _passwordValue, _nameValue];
NSLog(insertSQL);
const char *insert_stmt = [insertSQL UTF8String];
sqlite3_prepare_v2(_contactDB, insert_stmt,
-1, &statement, NULL);
if (sqlite3_step(statement) == SQLITE_DONE)
{
} else {
}
sqlite3_finalize(statement);
sqlite3_close(_contactDB);
}
I hope it's OK to answer my own question if it seems to work. Hopefully someone will find it useful. Would appreciate any feedback on where I might be going wrong.
sqlite3_stmt *statement;
const char *dbpath = [_databasePath UTF8String];
const char *insertSQL;
if (sqlite3_open(dbpath, &_contactDB) == SQLITE_OK)
{
insertSQL = "INSERT INTO CONTACTS (email, password, name) VALUES (?, ?, ?)";
if(sqlite3_prepare_v2(_contactDB, insertSQL, -1, &statement, NULL) == SQLITE_OK)
{
sqlite3_bind_text(statement, 1, [_emailValue UTF8String], -1, SQLITE_TRANSIENT);
sqlite3_bind_text(statement, 2, [_passwordValue UTF8String], -1, SQLITE_TRANSIENT);
sqlite3_bind_text(statement, 3, [_nameValue UTF8String], -1, SQLITE_TRANSIENT);
}
if (sqlite3_step(statement) == SQLITE_DONE)
{
//worked
} else {
//didn't work
}
sqlite3_finalize(statement);
sqlite3_close(_contactDB);
}
I'll try to explain what happened with your code and how it could be improved so that the crash would not occur. I totally agree with the usage of bound arguments, this answer is posted only as it represents an answer to how your crash can be fixed, and might help people that don't have the time to switch to bound statements.
Here's what happened:
sqlite3_prepare_v2() failed as your query string was invalid due to the fact that your strings contained the " characted
due to the above, statement was either NULL or contained a garbage value
sqlite3_step() crashed as an invalid pointer was passed as argument.
Here's the fix:
escape all your strings, by replacing " by \", this will generate a valid query; if you were using ' in your query, then you would have to replace ''s by \'
Example for email:
NSString *escapedEmail = [_emailValue stringByReplacingOccurrencesOfString:#"\"" withString:#"\\\""];
even if you're sure the query is correct, is still mandatory to check the result of sqlite3_prepare_v2() before using the statement in any other sqlite calls.
As a general note, you need to code very defensively when dealing with C API's as C doesn't forgive you if you forget to check for NULL pointers. Objective-C is more soft, as it allows you to send messages to nil objects.

How to update an entry in sqlite3?

Im super new to ios (Objective-C) and sql and Im following a tutorial of sqlite (specifically sqlite3) found here: http://www.tutorialspoint.com/ios/ios_sqlite_database.htm
and i implemented everything correctly. The problem is that if I try to enter information with the same reg id (The primary key which is used to find elements in the database), it complains about the key not being unique.
- (BOOL) saveData:(NSString*)registerNumber name:(NSString*)name
department:(NSString*)department year:(NSString*)year;
{
const char *dbpath = [databasePath UTF8String];
if (sqlite3_open(dbpath, &database) == SQLITE_OK)
{
NSString *insertSQL =
[NSString stringWithFormat:#"insert into studentsDetail (regno,name, department, year) values (\"%d\",\"%#\", \"%#\", \"%#\")",[registerNumber integerValue], name, department, year];
const char *insert_stmt = [insertSQL UTF8String];
sqlite3_prepare_v2(database, insert_stmt,-1, &statement, NULL);
int s = sqlite3_step(statement);
const char *errmsg = sqlite3_errmsg(database);
if (s == SQLITE_DONE)
{
sqlite3_reset(statement);
return YES;
}
else {
sqlite3_reset(statement);
return NO;
}
}
return NO;
}
How do I go about making the saveData: action actually update the entry inside the database instead of just being rejected?
Thanks!
"I want to extend it so that if I try to enter an existing reg id, it
will overwrite the remaining properties with the new ones"
If this is what you are trying to accomplish then you should not be using an INSERT statement. The purpose of the primary key is to protect the database from duplicate rows with the same primary key. When you look at it that way, the rejection is appropriate.
What you really want is to use INSERT OR REPLACE
If you're a beginner to both sql and objective c, I'd recommend a sqlite wrapper I created that is aimed at beginners: TankDB
Edit:
Code example:
INSERT OR REPLACE INTO studentsDetail (regno,name, department, year) values (\"%d\",\"%#\", \"%#\", \"%#\")"
Refer to this question to make sure that you don't actually mean to use 'UPSERT'. Beware that INSERT OR REPLACE does not update the existing row with the new information. It will completely delete the existing row and replace it.
Edit2: Open, prepare, step, finalize, close
const char *dbpath = [_databasePath UTF8String];
if(sqlite3_open(dbpath, &_database) == SQLITE_OK) {
const char *command = [query UTF8String];
// Perform the query
if (sqlite3_prepare_v2(_database, command, -1, &selectstmt, NULL) == SQLITE_OK) {
// For each row returned
while (sqlite3_step(selectstmt) == SQLITE_ROW) {
// Do stuff
}
}
sqlite3_finalize(selectstmt);
}
sqlite3_close (_database);

error: near "?": syntax error using sqlite and obj-c

After a suggestion on here I have tried to bind the values being passed into my queries, but I keep getting the syntax error: error: near "?": can someone explain why please?
NSString *sqLiteDb = [[NSBundle mainBundle] pathForResource:#"banklist" ofType:#"sqlite3"];
if(sqlite3_open([sqLiteDb UTF8String], &_database) == SQLITE_OK)
{
{
// prep statement
sqlite3_stmt *statement;
NSString *querySQL = #"UPDATE ? SET recipe_name=? WHERE cell_id=?";
NSLog(#"query: %#", querySQL);
const char *query_stmt = [querySQL UTF8String];
// preparing a query compiles the query so it can be re-used.
sqlite3_prepare_v2(_database, query_stmt, -1, &statement, NULL);
sqlite3_bind_text(statement, 1, [del.dayName UTF8String], -1, SQLITE_STATIC);
sqlite3_bind_text(statement, 2, [info.name UTF8String], -1, SQLITE_STATIC);
sqlite3_bind_int(statement, 1, del.tableRowNumber);
// process result
if (sqlite3_step(statement) != SQLITE_DONE)
{
NSLog(#"error: %s", sqlite3_errmsg(_database));
}
sqlite3_finalize(statement);
}
{
// prep statement
sqlite3_stmt *statement;
NSString *querySQL = #"UPDATE ? SET recipe_id = (SELECT key FROM recipes WHERE name = ?.recipe_name)";
NSLog(#"query: %#", querySQL);
const char *query_stmt = [querySQL UTF8String];
// preparing a query compiles the query so it can be re-used.
sqlite3_prepare_v2(_database, query_stmt, -1, &statement, NULL);
sqlite3_bind_text(statement, 1, [del.dayName UTF8String], -1, SQLITE_STATIC);
sqlite3_bind_text(statement, 2, [del.dayName UTF8String], -1, SQLITE_STATIC);
// process result
if (sqlite3_step(statement) != SQLITE_DONE)
{
NSLog(#"error: %s", sqlite3_errmsg(_database));
}
sqlite3_finalize(statement);
}
}
sqlite3_close(_database);
You use sqlite3_bind_xxx for values in your SQL, but not for table names. You have to use stringWithFormat for the table names and sqlite3_bind_xxx for the values.
You need to bind a value for each ? in the query. The 2nd parameter to the sqlite3_bind_xxx function is the index number. These are 1-based indexes.
In you 1st query you bind a value to the 1st ? two times. You probably need to change the sqlite3_bind_int call to pass 3 as the index instead of 1.
sqlite3_bind_int(statement, 3, del.tableRowNumber);
One other possible issue is your use of sqlite3_bind_text for the table name. This will put the table name in quotes. As suggested by Rob, you should use a string format to apply the table name but use sqlite3_bind_xxx for actual values you need in your query.

Resources