Currently, I write query for update data in iOS
NSString *query = [NSString stringWithFormat: #"update *from ericsson_review_form_field_table set value = %# where fieldId = %# and form_index = %d",strFValue,strFieldId,formIndex];
But it is not working.
Please tell me the sql query for update value.
Here you made a mistake in writing query to update any record, just try it
NSString *updateSQL = [NSString stringWithFormat:#"UPDATE EMPLOYEES set name = '%#', department = '%#', age = '%#' WHERE id = ?",
employee.name,
employee.department,
[NSString stringWithFormat:#"%d", employee.age]];
First Google and then ask..See below example for update
UPDATE table_name
SET column1 = value1
WHERE [condition];
UPDATE CUSTOMERS
SET ADDRESS = 'Pune', SALARY = 1000.00;
NSString *updateSQL = [NSString stringWithFormat:#"update table_name SET name='%#' where regno='1000'"];
Hope it helps you....
Simple way to update record in table is as bellow
UPDATE table2
SET table2.col1 = table1.col1,
table2.col2 = table1.col2,
...
FROM table1, table2
WHERE table1.memberid = table2.memberid
Currently my code is
- (BOOL)updateReviewFields:(NSString *)strFieldId andFormIndex:(int)formIndex withFValue:(NSString *)strFValue{
sqlite3_stmt *statement = nil;
NSString *query;
if(sqlite3_open([[appDelegate databasePath] UTF8String],&database) == SQLITE_OK){
query = [NSString stringWithFormat: #"update ericsson_review_form_field_table set value = %# where fieldId = %# and form_index = %d",strFValue,strFieldId,formIndex];
if(sqlite3_prepare_v2(database, [query UTF8String], -1, &statement, NULL)
== SQLITE_OK){
sqlite3_bind_text(statement, 1, [strFieldId UTF8String], -1, SQLITE_TRANSIENT);
sqlite3_bind_text(statement, 13, [strFValue UTF8String], -1, SQLITE_TRANSIENT);
if(sqlite3_step(statement))
return YES;
else
return NO;
}
sqlite3_finalize(statement);
}
sqlite3_close(database);
return NO;
}
and now it is working fine.
You posted a code sample:
- (BOOL)updateReviewFields:(NSString *)strFieldId andFormIndex:(int)formIndex withFValue:(NSString *)strFValue{
sqlite3_stmt *statement = nil;
NSString *query;
if(sqlite3_open([[appDelegate databasePath] UTF8String],&database) == SQLITE_OK){
query = [NSString stringWithFormat: #"update ericsson_review_form_field_table set value = %# where fieldId = %# and form_index = %d",strFValue,strFieldId,formIndex];
if(sqlite3_prepare_v2(database, [query UTF8String], -1, &statement, NULL)
== SQLITE_OK){
sqlite3_bind_text(statement, 1, [strFieldId UTF8String], -1, SQLITE_TRANSIENT);
sqlite3_bind_text(statement, 13, [strFValue UTF8String], -1, SQLITE_TRANSIENT);
if(sqlite3_step(statement))
return YES;
else
return NO;
}
sqlite3_finalize(statement);
}
sqlite3_close(database);
return NO;
}
I don't see how the above could possibly work.
You're using sqlite3_bind_text, but you don't have any ? placeholders in your SQL to bind to. (You should check the return code from your sqlite3_bind_text calls and I'd be shocked if they're returning SQLITE_OK.)
You're binding the first item and the thirteenth item. The latter bind call, to the thirteenth ?, certainly wouldn't work unless you had at least thirteen ? placeholders.
You're returning immediately after calling sqlite3_step, never hitting your sqlite3_finalize statement and you'd undoubtedly leak memory as a result. You'd also never close the database if you got to these return statements after sqlite3_step.
You're testing if (sqlite3_step(...)). That doesn't make sense, because sqlite3_step always returns a non-zero value (either SQLITE_DONE upon success or some non-zero error code on error).
I'd suggest logging sqlite3_errmsg if any of the SQLite calls fail.
I might suggest changing the return value of the method to be the number of rows that were updated. This way, you can differentiate between (a) successful update; (b) no rows updated (but no errors); and (c) a failure. I might return negative value on error, zero if no rows matched the WHERE criteria, and a positive value, n, if n rows were successfully updated. I use sqlite3_changes to determine how many rows were updated.
Finally, I'd seriously advise against using stringWithFormat to build your SQL (at least if the string values include any user-provided input, because you expose yourself to quoting and/or SQL injection problems).
So, instead, I'd suggest:
/** Update fields
*
* #param strFieldId The fieldId column string value
* #param formIndex The form_index integer value
* #param strFValue The string to which the `value` column should be updated.
*
* #return Returns the number of rows updated. Return negative value on failure. Return zero if no rows matched the WHERE criteria.
*/
- (int)updateReviewFields:(NSString *)strFieldId andFormIndex:(int)formIndex withFValue:(NSString *)strFValue {
AppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
sqlite3 *database;
NSString *databasePath = [appDelegate databasePath];
sqlite3_stmt *statement = nil;
int rowCount = -1;
int rc;
if ((rc = sqlite3_open([databasePath UTF8String], &database)) != SQLITE_OK) {
NSLog(#"Unable to open database: %# (%ld)", databasePath, (long)rc);
return rowCount;
}
const char *query = "update ericsson_review_form_field_table set value = ? where fieldId = ? and form_index = ?";
if ((rc = sqlite3_prepare(database, query, -1, &statement, NULL)) != SQLITE_OK) {
NSLog(#"sqlite3_prepare fail: %s (%ld)", sqlite3_errmsg(database), (long)rc);
sqlite3_close(database);
return rowCount;
}
if ((rc = sqlite3_bind_text(statement, 1, [strFValue UTF8String], -1, NULL)) != SQLITE_OK) {
NSLog(#"sqlite3_bind_text 1 fail: %s (%ld)", sqlite3_errmsg(database), (long)rc);
} else if ((rc = sqlite3_bind_text(statement, 2, [strFieldId UTF8String], -1, NULL)) != SQLITE_OK) {
NSLog(#"sqlite3_bind_text 2 fail: %s (%ld)", sqlite3_errmsg(database), (long)rc);
} else if ((rc = sqlite3_bind_int(statement, 3, formIndex)) != SQLITE_OK) {
NSLog(#"sqlite3_bind_int 3 fail: %s (%ld)", sqlite3_errmsg(database), (long)rc);
} else if ((rc = sqlite3_step(statement)) != SQLITE_DONE) {
NSLog(#"sqlite3_step fail: %s (%ld)", sqlite3_errmsg(database), (long)rc);
} else {
rowCount = sqlite3_changes(database);
}
sqlite3_finalize(statement);
sqlite3_close(database);
return rowCount;
}
Related
I am selecting data from sqlite database. Problem is that using following code it works some time. But lets say we call this method for any other table twice then it shows null select statement for other method. Is any thing wrong in method so that if we use same for other tables some time it works some time not.
-(void)getAssessmentNumber:(NSString *)dbPath{
appDelegate=[[UIApplication sharedApplication]delegate];
NSString*fileDBPath=[[NSBundle mainBundle] pathForResource:#"Database" ofType:#"sqlite"];
if (sqlite3_open([fileDBPath UTF8String], &database) == SQLITE_OK)
{
// NSLog(#"%#",[self getDBPath]);
NSString *querySQL = [NSString stringWithFormat:#"Select Am.AssessmentID , Am.AssessmentName From AssessmentMaster Am LEFT JOIN AssessmentDepartmentMapping M ON M.AssessmentID = Am.AssessmentID LEFT JOIN DepartmentListing d ON d.departmentID =M.departmentID where d.departmentID = '%#'",appDelegate.departmentID];
NSLog(#"%#",querySQL);
const char *sql = [querySQL UTF8String];
sqlite3_stmt *selectstmt;
NSError *error;
[appDelegate.assessmentNumberArray removeAllObjects];
if (sqlite3_prepare_v2(database, sql, -1, &selectstmt, NULL) == SQLITE_OK)
{
while (sqlite3_step(selectstmt) == SQLITE_ROW)
{
NSInteger primaryKey = sqlite3_column_int(selectstmt, 0);
AssessmentListening *asmObj = [[AssessmentListening alloc] initWithPrimaryKey:primaryKey];
asmObj.assessmentID=[NSString stringWithFormat:#"%d",primaryKey];
asmObj.assessmentName = [NSString stringWithUTF8String:(char *)sqlite3_column_text(selectstmt, 1)];
[appDelegate.assessmentNumberArray addObject:asmObj];
}
}
else {
NSAssert1(0, #"Failed to create writable database file with message '%#'.", [error localizedDescription]);
}
// sqlite3_finalize(selectstmt);
}
sqlite3_close(database);
}
Is this fine for getting the data from table?
Your code needs a little cleanup.
- (void)getAssessmentNumber:(NSString *)dbPath {
NSString *fileDBPath = [[NSBundle mainBundle] pathForResource:#"Database" ofType:#"sqlite"];
if (sqlite3_open([fileDBPath UTF8String], &database) == SQLITE_OK) {
appDelegate = [[UIApplication sharedApplication] delegate];
[appDelegate.assessmentNumberArray removeAllObjects];
const char *sql = "Select Am.AssessmentID, Am.AssessmentName From AssessmentMaster Am LEFT JOIN AssessmentDepartmentMapping M ON M.AssessmentID = Am.AssessmentID LEFT JOIN DepartmentListing d ON d.departmentID = M.departmentID where d.departmentID = ?";
sqlite3_stmt *selectstmt;
if (sqlite3_prepare_v2(database, sql, -1, &selectstmt, NULL) == SQLITE_OK) {
sqlite3_bind_text(selectstmt, 0, [appDelegate.departmentID UTF8String], -1, SQLITE_TRANSIENT);
while (sqlite3_step(selectstmt) == SQLITE_ROW) {
NSInteger primaryKey = sqlite3_column_int(selectstmt, 0);
AssessmentListening *asmObj = [[AssessmentListening alloc] initWithPrimaryKey:primaryKey];
asmObj.assessmentID = [NSString stringWithFormat:#"%d", primaryKey];
asmObj.assessmentName = [NSString stringWithUTF8String:(char *)sqlite3_column_text(selectstmt, 1)];
[appDelegate.assessmentNumberArray addObject:asmObj];
}
sqlite3_finalize(selectstmt);
} else {
NSLog(#"Unable to prepare statement: %s", sqlite3_errmsg(database));
}
sqlite3_close(database);
} else {
NSLog(#"Unable to open the database from %#: %s", fileDBPath, sqlite3_errmsg(database);
}
}
Note all of the changes:
Only close the database if it is opened.
Only finalize the statement if it is prepared.
Don't build queries with stringWithFormat. Use the proper sqlite3_bind_xxx function to bind the values to the query. This ensures special characters are escaped and properly deals with quoting.
Use proper error checking. Use sqlite3_errmsg to get the error.
I've used the following method in my app,
-(int) getMax:(NSString *)subItemName second :(int) tableID
{
int count1=0;
sqlite3_stmt *statement;
NSString *query = [NSString stringWithFormat:#"Select MAX(NoOfItems) from billTable where SubItemName='%#' AND TableID='%d'",subItemName,tableID];
if (sqlite3_prepare_v2(_database, [query UTF8String], -1, &statement, nil)== SQLITE_OK) {
while (sqlite3_step(statement) == SQLITE_ROW) {
count1 = [[NSString stringWithUTF8String:(char *) sqlite3_column_text(statement, 0)]intValue];
}
sqlite3_step (statement);
}
return count1;
}
As you can see that the my query will return the no of rows (an integer), suppose if my query returns a NULL value(if there is no such exists for the where clause condition in my database it returns NULL value. How to check it returns NULL after the query has been executed?
You can call sqlite3_column_type() to find out what type a column value has:
if (sqlite3_prepare_v2(_database, [query UTF8String], -1, &statement, nil)== SQLITE_OK) {
if (sqlite3_step(statement) == SQLITE_ROW) {
if (sqlite3_column_type(statement, 0) == SQLITE_NULL)
count1 = -1; // or whatever
else
count1 = sqlite3_column_int(statement, 0);
}
sqlite3_finalize(statement);
}
I had debugged code but don't know why While statement is not executing . After putting NSlog I came to know it's mismatching the result. 101 and SQLITE_ROW is equal to 100.
But query has result. If I fetch Select * from table name its returning me result and while statement executes. If I fetch result
sql_stmt = [NSString stringWithFormat:#"SELECT * FROM DeviceType WHERE upper(TypeName) = upper('%#')", deviceType];
While statement never execute so please help. don't know where is the problem.
Here is the code:
NSArray* paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask,YES);
NSString* documentsDirectory = [paths objectAtIndex:0];
NSString* path = [documentsDirectory stringByAppendingPathComponent:#"ClientDB.sqlite"];
NSString* sql_stmt = [self searchStringForLocalData];
BOOL found = NO;
if (sqlite3_open([path UTF8String], &database) == SQLITE_OK)
{
const char* sql1 = [sql_stmt UTF8String];
sqlite3_stmt *statement;
NSNumber *typeCount;
typeCount = 0;
if (sqlite3_prepare_v2(database, sql1, -1, &statement, NULL) == SQLITE_OK)
{
NSLog(#" %d, %d ",sqlite3_step(statement),SQLITE_ROW);
while (sqlite3_step(statement) == SQLITE_ROW) {
// The second parameter indicates the column index into the result set.
int primaryKey1 = sqlite3_column_int(statement, 0);
NSNumber *typeId = [[NSNumber alloc] initWithInt:primaryKey1];
NSString *typeName =[NSString stringWithUTF8String:(char *)sqlite3_column_text(statement, 1)];
NSString* sql_stmt1 = [NSString stringWithFormat:#"SELECT COUNT(*) FROM Devices WHERE DeviceTypeId =%d",primaryKey1];
const char *sql1 = [sql_stmt1 UTF8String];
sqlite3_stmt *statement;
NSNumber *typeCount;
typeCount = 0;
As already mentioned in a comment, the code calls sqlite3_step once for the NSLog, and then a second time in the condition of the while loop.
If your query returns exactly one record, the first sqlite3_step call will step to that record, and the second sqlite3_step call will then report (correctly) that no further results are available.
Just remove that NSLog call.
Alternatively, call sqlite3_step only once, and use the same return value for both the logging and the loop:
int rc;
...
while (1) {
rc = sqlite3_step(statement);
NSLog(#" %d, %d ", rc, SQLITE_ROW);
if (rc != SQLITE_ROW)
break;
...
}
if (rc != SQLITE_DONE)
NSLog(#"error: %s", sqlite3_errmsg(database));
Try to use the following syntax
while(sqlite3_step(stmt)!=SQLITE_DONE)
{
//do ur processing
for(i=0;i<NO_OF_COLS;i++)
{
char * tmp1=sqlite3_column_text(stmt,i);
if(tmp1!=NULL)
{
//use the value
}
else
{
//use a default
}
}
}
It shows that your table is totally empty. You may want to check your insert whether it works correctly. If you're using sqlite3_prepare_v2 to prepare your statement with some ? marks, remember to execute your query after all. Simply like this:
if(sqlite3_step(stmt) == SQLITE_DONE) NSLog(#"INSERTED");
else NSLog(#"NO INSERTED");
Note: It will display error only if your query is wrong, but not your prepared statement was executed or not.
I am trying to update my sqlite database but this code is not working for me.
Please help me to find what is wrong with this.
-(BOOL)StoreFavourite:(NSString*)fav :(int)DuaId
{
NSString* mydbpath=[self pathfinder];
const char *dbpath=[mydbpath UTF8String];
if(sqlite3_open(dbpath,&database )==SQLITE_OK)
{
NSString *query = [NSString stringWithFormat:#"UPDATE Dua SET
favourite=\'%#\' WHERE dua_id=%d ",fav,DuaId];
const char *query_statement=[query UTF8String];
if(sqlite3_prepare_v2(database, query_statement, -1, &statement, NULL)==SQLITE_OK)
{
while(sqlite3_step(statement) == SQLITE_DONE)
{
return YES;
}
sqlite3_finalize(statement);
}
}
return YES;
}
Please check your "mydbpath" by putting NSLog.I think you have given incorrect path.
Also try to use:
NSString *query = [NSString stringWithFormat:#"UPDATE Dua SET favourite='%#' WHERE dua_id=%d ",fav,DuaId];
here are some reason for due to which the sqlite3_prepare_v2 != SQLITE_OK :
1.The table may not present into the database.
2.Wrong query statement .
3.Wrong column name into the query statement.
You can find the exact problem using error statement by putting following in else:
NSAssert1(0, #"Error while inserting data. '%s'", sqlite3_errmsg(database))
please try in following manner
-(BOOL)StoreFavourite:(NSString*)fav :(int)DuaId
{
sqlite3_stmt *statement=nil;
NSString *mydbpath=[self pathfinder];
NSString *query;
if(sqlite3_open([mydbpath UTF8String],&database) == SQLITE_OK)
{
query = [NSString stringWithFormat: #"update Dua set favourite=? where dua_id=?"];
if(sqlite3_prepare_v2(database, [query UTF8String], -1, &statement, NULL)
== SQLITE_OK)
{
sqlite3_bind_int(statement, 2, DuaId);
sqlite3_bind_text(statement, 1, [fav UTF8String], -1, SQLITE_TRANSIENT);
if(sqlite3_step(statement))
{
return YES;
}
else
{
return NO;
}
}
sqlite3_finalize(statement);
}
sqlite3_close(database);
return NO;
}
hi all
i have some problem in using sqlite in IOS. i have select data from database, and then i want to save that data in a variable. But when i use while(sqlite3_step(statement) == SQLITE_ROW) loop, the code never execute.
here is my code :
-(void)retrieveProjectNameFromDb:(NSString *)segmenId{
NSString *query;
NSString *nameProjectStr;
NSString *dbPath = [[NSBundle mainBundle] pathForResource:#"database" ofType:#"sqlite"];
if (sqlite3_open([dbPath UTF8String], &db) != SQLITE_OK) {
sqlite3_close(db);
NSAssert(0, #"Database failed to open.");
}else {
query = [NSString stringWithFormat:#"SELECT remote_projectname, remote_base_uri FROM REMOTE_SETTING WHERE remote_settingid = '%#' ORDER BY remote_projectname", segmenId];
NSLog(#"query : %#", query);
}
sqlite3_stmt *statement;
if(sqlite3_prepare_v2(db, [query UTF8String], -1, &statement, nil)==SQLITE_OK){
NSLog(#"sqlite row : %d", SQLITE_ROW);
NSLog(#"sqlite 3 : %d", sqlite3_step(statement));
while (sqlite3_step(statement) == SQLITE_ROW) {
char *nameProject = (char *)sqlite3_column_text(statement, 0);
if (nameProject == nil) {
NSLog(#"UNNAMED");
}else {
NSLog(#"else");
nameProjectStr = [NSString stringWithUTF8String:nameProject];
}
projectName.text = nameProjectStr;
nameProject = nil;
}
NSLog(#"project name : %#", projectName.text);
sqlite3_close(db);
}
}
when i nslog the value, sqlite3_step(statement) always show 101 and sqlite_row always show 100. Why it can happen??
can somebody help me, please?
thank you
Regards
-risma-
As you mentioned sqlite3_step(statement) always show 101 which means sqlite3_step has finished executions hence it means your sql query is not returning any rows from database. I would recommend you to first check in database if any record exists in table REMOTE_SETTING for remote_settingid which you are referring.
For your reference I took following constant snippet from sqlite.org
#define SQLITE_DONE 101 /* sqlite_step() has finished executing */
Remove the NSLog entry in which you are having sqlite3_step(). Since you have your NSLog statement executing sqlite3_step(), the record is already stepped through here. Hence, your while loop won't execute as there are no more rows to step through.
I think this will surely help you. :)
From your description of the logging output I would guess that your query is returning an empty row set. However I can see two other problems here:
You discard the result of your first call to sqlite3_step, because you log it then immediately call sqlite3_step again. That means you will miss the first row.
You probably should not be closing the database after a single query. You should finalize the statement after the query, but only close the database when your app shuts down.
Try:
if(sqlite3_prepare_v2(db, [query UTF8String], -1, &statement, nil)==SQLITE_OK){
NSLog(#"sqlite row : %d", SQLITE_ROW);
int stepResult = sqlite3_step(statement);
NSLog(#"sqlite 3 : %d", stepResult);
while (stepResult == SQLITE_ROW) {
char *nameProject = (char *)sqlite3_column_text(statement, 0);
if (nameProject == nil) {
NSLog(#"UNNAMED");
}else {
NSLog(#"else");
nameProjectStr = [NSString stringWithUTF8String:nameProject];
}
projectName.text = nameProjectStr;
nameProject = nil;
stepResult = sqlite3_step(statement);
}
NSLog(#"project name : %#", projectName.text);
sqlite3_finalize(&statement);
}
Try with something like this..
sqlite3 *database1;
NSString *sqlStatement1 = #"";
if(sqlite3_open([databasePath UTF8String], &database1) == SQLITE_OK)
{
sqlStatement1 = [NSString stringWithString:#"SELECT uniqueid from shortlisted"];
sqlite3_stmt *compiledStatement1;
if(sqlite3_prepare_v2(database1, [sqlStatement1 cStringUsingEncoding:NSUTF8StringEncoding], -1, &compiledStatement1, NULL) == SQLITE_OK)
{
while(sqlite3_step(compiledStatement1) == SQLITE_ROW)
{
NSString * str = [NSString stringWithUTF8String:(char *)sqlite3_column_text(compiledStatement, 1)];
}
}
sqlite3_finalize(compiledStatement1);
sqlite3_close(database1);
}
Also close database instance whenever you open them.. if you are not closing an instance then that can cause issues..
Sorry I am pasting this from my project.. but actually I am in a bit hurry... I'll modify this answer when I reach home...