I have a simple program that update a record of a table
The table is "person" with two columns "name" and "age";
some records have been inserted, as follows:
name age
tom 20
andy 30
han 25
Now I am writing a program to update a row in the table:
NSString *database=[[NSBundle mainBundle] pathForResource:#"mytable" ofType:#"sqlite"];
sqlite3_open([database UTF8String],&contactDB);
NSString *text=#"andy";
NSString *query=[NSString stringWithFormat:#"UPDATE person SET age=%d WHERE name='%#'",30,text];
sqlite3_stmt *statement;
sqlite3_prepare_v2(contactDB,[query UTF8String],-1,&statement,NULL);
sqlite3_finalize(statement);
sqlite3_close(contactDB);
The program works fine, but the database is not updated (I am using SQLite Manager to browser the database)
When I try reading from database, it works well:
NSString *database=[[NSBundle mainBundle] pathForResource:#"mytable" ofType:#"sqlite"];
sqlite3_open([database UTF8String],&contactDB);
NSString *query1=[NSString stringWithFormat:#"SELECT * FROM person WHERE age=%d;",30];
sqlite3_stmt *statement;
sqlite3_prepare_v2(contactDB,[query1 UTF8String],-1,&statement,NULL);
sqlite3_step(statement);
NSString *result=[[NSString alloc] initWithUTF8String:(const char *)sqlite3_column_text(statement, 0)];
label.text=result;
sqlite3_finalize(statement);
sqlite3_close(contactDB);
-(void)updateSetting:(NSArray *)arr
{
if(sqlite3_open([databasePath UTF8String],&myDatabase)==SQLITE_OK)
{
sqlite3_stmt *compiledStmt;
NSString *sqlStmt=[NSString stringWithFormat:#"UPDATE setting SET flow='%#',formate='%#' WHERE primaryKey=%i;",[arr objectAtIndex:0],[arr objectAtIndex:1],1];
if(sqlite3_prepare_v2(myDatabase, [sqlStmt UTF8String],-1,&compiledStmt, NULL)==SQLITE_OK)
{
NSLog(#"Successful update");
}
sqlite3_step(compiledStmt);
sqlite3_close(myDatabase);
}
}
I already faced this issues. Whats the problem behind this is you passed the query as a string format so you have to use the ; at the end of the query statement.
NSString *query=[NSString stringWithFormat:#"UPDATE questionbank SET age=%d WHERE name='%#';",30,text];
Please make a checking like below before you perform your sqlite3_step method.
const char *sqlQuery = "UPDATE SETTINGS SET someFlag = 0";
sqlite3_stmt *insertStatement = nil;
int success = 0;
if(sqlite3_prepare_v2(sqliteDatabase, sqlQuery, -1, &insertStatement, NULL) == SQLITE_OK)
{
success = sqlite3_step(insertStatement);
if(insertStatement)
{
sqlite3_finalize(insertStatement);
}
if(success == SQLITE_ERROR)
{
return NO;
}
return YES;
}
return NO;
So that you can figure out, where the problem is.
You need to check whether you could access and open the database or not. Simply place your update segment in a if-statement like this: if(sqlite3_open([databasePath UTF8String], &database) == SQLITE_OK).
Also try to add NSLog(#"%s", sqlite3_errmsg(database)); after your prepare to see if there was any errors.
The answer for this problem is that the database in the main bundle is read-only
I can not insert data into sqlite3 file on XCode
Related
In my "viewWillAppear" callback I attempt to populate a UITableViewController with data from SQLite database for the user to see.
However, what I noticed was if I switch to another tab, commit a new row of data into SQLite and switch back to the UITableViewController it does not update with the new row I just added to the database. I have to quit out of the app completely and navigate back to the UITableViewController in order to see the new row reflected on the table view.
How do I get around this problem (i.e. how do I force always showing the very latest information in SQLite on the UITableViewController after switching back and forth a bunch of times?)
Would appreciate all / any advice.
Here is the code:
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
NSLog(#"viewwillappear");
//[[self tableView] reloadData];
int rc=-1;
if (databasePath == nil) {
NSLog(#"database path is NIL. Trying to set it");
databaseName = #"mymemories.sqlite";
NSArray *documentPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDir = [documentPaths objectAtIndex:0];
databasePath = [documentsDir stringByAppendingPathComponent:databaseName];
return;
}
rc = sqlite3_open([databasePath UTF8String], &database);
if(rc == SQLITE_OK) {
memoriesArray = [[NSMutableArray alloc]init ];
sqlite3_stmt *statement = nil;
NSString *fullQuery = #"SELECT * FROM memories";
const char *sql = [fullQuery UTF8String];
if(sqlite3_prepare_v2(database, sql, -1, &statement, NULL)!=SQLITE_OK)
NSAssert1(0, #"Error preparing statement '%s'", sqlite3_errmsg(database));
else
{
while(sqlite3_step(statement) == SQLITE_ROW)
{
NSString *place= [NSString stringWithUTF8String:(const char*)sqlite3_column_text(statement, 4)];
//[User setName:[NSString stringWithUTF8String:(const char*)sqlite3_column_text(statement, 1)]];
//[User setAge:[NSString stringWithUTF8String:(const char*)sqlite3_column_text(statement, 2)]];
[memoriesArray addObject:place];
//[currentUser release];
}
}
sqlite3_finalize(statement);
sqlite3_close(database);
}
}
Also in case this is relevant, here is the code that commits to the SQLite database:
NSData * blob = [NSData dataWithContentsOfURL:recordedTmpFile];
int rc=-1;
rc = sqlite3_open([databasePath UTF8String], &database);
if(rc == SQLITE_OK) {
sqlite3_exec(database, "BEGIN", 0, 0, 0);
NSLog(#"Connected To: %#",databasePath);
sqlite3_stmt *updStmt =nil;
const char *sql = "INSERT INTO memories (data,place) VALUES (?,?);";
rc = sqlite3_prepare_v2(database, sql, -1, &updStmt, NULL);
if(rc!= SQLITE_OK)
{
NSLog(#"Error while creating update statement:%#", sqlite3_errmsg(database));
}
sqlite3_bind_text( updStmt, 2, [[tags text] UTF8String], -1, SQLITE_TRANSIENT);
rc = sqlite3_bind_blob(updStmt, 1, [blob bytes], [blob length] , SQLITE_BLOB);
if((rc = sqlite3_step(updStmt)) != SQLITE_DONE)
{
NSLog(#"Error while updating: %#", sqlite3_errmsg(database));
sqlite3_reset(updStmt);
}
sqlite3_exec(database, "COMMIT", 0, 0, 0);
//rc = sqlite3_reset(updStmt);
sqlite3_close(database);
}
As an extension of an explanation of Darren's answer.
First off his answer is correct.
Secondly you need to use an NSMutableArray to ensure consistency, this is where you are going wrong by not updating it as you should
The steps you should be taking to ensure consistency are the following:
Loading Data into Table
In viewDidLoad, call your SQL statement and load it into your array
in viewWillAppear ensure that your array contains data, if not display a notice that no results were returned
Saving Data into Database
Update the change to the array (or datasource)
Update the Database with the updated datasource to ensure consistency
Update the table with one of the 4 UITableView reloading methods
Using the NSMArray to ensure consistency between updates and app loads is fairly common practise has be recommended to me in the past by fellow co workers with decades of experience.
Note:
You will need to synchronise the datasource to ensure that 1 thread is accessing it at any 1 time otherwise you will get a crash.
Assuming you read your SQL data into an array, then use this array to build the UITableView, when you add a record to your SQL database, you either need to also add it to the array used to build the table, or re-read the data from the database into the array.
I'm very confused why the SELECT statement doesn't work correctly. It doesn't give me any errors, just returns null. I know it is writing the string correctly and the right string is there, it's just not reading it correctly. Everything as far as I know is correct because I use the same SQLstmt "method" for many other methods/functions similar to this. This one just doesn't make sense on why it shouldn't work.
- (NSString *)returnNote {
selStmt=nil;
NSLog(#"Reading note");
NSString *SQLstmt = [NSString stringWithFormat:#"SELECT 'Notes' FROM '%#' WHERE Exercises = '%#';", currentRoutine, currentExercise];
// Build select statements
const char *sql = [SQLstmt UTF8String];
if (sqlite3_prepare_v2(database, sql, -1, &selStmt, NULL) != SQLITE_OK) {
selStmt = nil;
}
// Building select statement failed
if (!selStmt) {
NSAssert1(0, #"Can't build SQL to read Exercises [%s]", sqlite3_errmsg(database));
}
NSString *note = [NSString stringWithFormat:#"%s", sqlite3_column_text(selStmt, 0)];
sqlite3_reset(selStmt); // reset (unbind) statement
return note;
}
You're not calling sqlite3_step. The statement is never executed.
NSString *querySQLS1 = [NSString stringWithFormat: #"SELECT Notes FROM \"%#\" where Exercises=\"%#\"", currentRoutine, currentExercise];
sqlite3_stmt *statements;
const char *query_stmts1 = [querySQLS1 UTF8String];
if(sqlite3_prepare_v2(UsersDB, query_stmts1, -1, &statement, NULL) == SQLITE_OK)
{
NSLog(#"in prepare");
if (sqlite3_step(statement) == SQLITE_ROW)
{
NSLog(#"Query executed");
}
else {
NSLog(#"in else");
}
sqlite3_finalize(statement);
}
I am getting EXC_BAD_ACCESS when I attempt to do anything with the value I'm selecting from the local SQLITE database on an iPhone development. The code for my function is
-(void) updateFromDB {
// Setup the database object
sqlite3 *database;
// Open DB
if(sqlite3_open([databasePath UTF8String], &database) == SQLITE_OK) {
NSString *query = [NSString stringWithFormat:#"SELECT MOD_ID FROM MODULE;"];
//NSLog(#"QUERY: %#",query);
// Prepare statement
sqlite3_stmt *statement;
if(sqlite3_prepare_v2(database, [query UTF8String], -1, &statement, NULL) == SQLITE_OK) {
// Execute SQL
while (sqlite3_step(statement) == SQLITE_ROW) {
// Get MOD_IDs
NSInteger MOD_ID = sqlite3_column_int(statement, 0);
NSString *ID = [NSString stringWithFormat:#"%#",MOD_ID];
//=======================
// Get Notice Module Data
//=======================
if (MOD_ID == 1) {
self.noticeModule = [[ModuleSetting alloc] initWithID:ID];
}
}
} else {
NSAssert1(0,#"Error: failed to prepare statement. '%s'", sqlite3_errmsg(database));
}
// Release the compiled statement from memory
sqlite3_finalize(statement);
} else {
sqlite3_close(database);
NSAssert1(0,#"Failed to open database. '%s'",sqlite3_errmsg(database));
}
sqlite3_close(database);
}
The bad access occurs on the line
NSString *ID = [NSString stringWithFormat:#"%#",MOD_ID];
Thanks for any help you can offer!
%# denotes objects. But MOD_ID seems to be an integer. So your format should be %d,
NSString *ID = [NSString stringWithFormat:#"%d", MOD_ID];
You can't use %# in format strings for integers, only for Obj-C objects. For integers, use %d (or for NSInteger, I think it is recommended to use %ld).
Have a look at the String Format Specifiers guide.
MOD_ID is not a pointer, so %# isn't correct.
Use below
NSInteger MOD_ID = sqlite3_column_int(statement, 0);
NSString *ID = [NSString stringWithFormat:#"%d",MOD_ID];
I am using what, according to my Xcode debugger, is proper syntax to delete a row from a table in my project. However, when I go back to check my database, it still exists. My other SQL syntax for inserting entries is correct, so I'm not sure what I'm doing wrong. NSLogs confirm both variables are being sent correctly:
-(void) deleteSelectedRowFromTable: (NSString *) tableName cityName:(NSString *)city
{
[self openDB];
NSString *sqlStr = [NSString stringWithFormat:#"DELETE FROM %# WHERE city LIKE %#", tableName, city];
const char *sql = [sqlStr UTF8String];
sqlite3_stmt *statement;
if (sqlite3_prepare_v2(db, sql, -1, &statement, nil) == SQLITE_OK) {
NSAssert1(0, #"Error: failed to prepare statement with message '%s'.", sqlite3_errmsg(db));
}
sqlite3_finalize(statement);
sqlite3_close(db);
}
Try this statement
NSString *sqlStr = [NSString stringWithFormat:#"DELETE FROM '%#' WHERE city LIKE '%#%%'", tableName, city];
Check that the operand to LIKE is a string (should have quotation marks around it). I've never used XCode, but if you change your 5th line to read:
NSString *sqlStr = [NSString stringWithFormat:#"DELETE FROM %# WHERE city LIKE '%#'", tableName, city];
Does that work?
you have just prepared the statement, you should step that statement.
-(void) deleteSelectedRowFromTable: (NSString *) tableName cityName:(NSString *)city
{
[self openDB];
NSString *sqlStr = [NSString stringWithFormat:#"DELETE FROM %# WHERE city LIKE %#", tableName, city];
const char *sql = [sqlStr UTF8String];
sqlite3_stmt *statement;
if (sqlite3_prepare_v2(db, sql, -1, &statement, nil) != SQLITE_OK)
{
/**this one will execute when there is error in your query**/
NSAssert1(0, #"Error: failed to prepare statement with message '%s'.", sqlite3_errmsg(db));
}
else
{
/************just add this one****************/
sqlite3_step(statement);
}
sqlite3_finalize(statement);
sqlite3_close(db);
}
i hope this one will help you.
Hi I have a function which basically tries to insert some data returned from a REST call.
- (void)syncLocalDatabase{
NSString *file = [[NSBundle mainBundle] pathForResource:#"pickuplines" ofType:#"db"];
NSMutableString *query = [[NSMutableString alloc] initWithFormat:#""];
sqlite3 *database = NULL;
char *errorMsg = NULL;
if (sqlite3_open([file UTF8String], &database) == SQLITE_OK) {
for(PickUpLine *pickupline in pickUpLines){
[query appendFormat:#"INSERT INTO pickuplines VALUES(%d,%d,%d,'%#','YES')", pickupline.line_id, pickupline.thumbsUps, pickupline.thumbsDowns, [pickupline.line stringByReplacingOccurrencesOfString:#"'" withString:#"`"]];
NSLog(query);
int result = sqlite3_exec(database, [query UTF8String], NULL, NULL, &errorMsg);
if (result!=SQLITE_OK) {
printf("\n%s",errorMsg);
sqlite3_free(errorMsg);
}
//sqlite3_step([query UTF8String]);
[query setString:#""];
}//end for
}//end if
[query release];
sqlite3_close(database); }
everything seems fine query string in log statement is also fine but the data does not gets inserted. Where as a counterpart of this function for select statement works well.
Here is the counter part
- (void)loadLinesFromDatabase{
NSString *file = [[NSBundle mainBundle] pathForResource:#"pickuplines" ofType:#"db"];
sqlite3 *database = NULL;
if (sqlite3_open([file UTF8String], &database) == SQLITE_OK) {
sqlite3_exec(database, "SELECT * FROM pickuplines", MyCallback, linesFromDatabase, NULL);
}
sqlite3_close(database);
}
I have implemented callback & it works fine.
I am a little new to Sqlite can someone please point out what am I doing wrong.
Thanx
You can always use Crystalminds' SQLiteDatabase:
http://www.crystalminds.nl/?p=1342
They made an incredibly easy-to-use Database Library, so no more problems with difficult code! I've been using this for some time now, and i can't imagine having to do without!