I'm trying to display food by type to a user. The different types of foods are different elements in a table (fruits, veggies, meats, etc). I have all the foods in one database using sqlite. How can I query this database using objective c so that I can display only the correct type of food the user selected in the next view's table?
We use FMDB in two apps. It works fine.
-(NSArray *)GetAllFoods
{
NSMutableArray *filesArray = [[NSMutableArray alloc] init];
// Open the database from the users filessytem
NSString *DBPath = [ClsCommonFunctions GetDatabasePath];
if ([self OpenDBWithPath:DBPath])
{
// Setup the SQL Statement and compile it for faster access
const char *sqlStatement = "your query";
sqlite3_stmt *compiledStatement;
if(sqlite3_prepare_v2(filesDB, sqlStatement, -1, &compiledStatement, NULL) == SQLITE_OK) {
while(sqlite3_step(compiledStatement) == SQLITE_ROW)
{
// Need to get data from database...
NSSstring *foodObj = [NSString stringWithUTF8String:(char *)sqlite3_column_text(compiledStatement, 0)]
[filesArray addObject:foodObj];
FileObj = nil;
}
}
// Release the compiled statement from memory
sqlite3_finalize(compiledStatement);
sqlite3_close(filesDB);
}
return filesArray;
Related
I have more than 100 records in a database of a particular user. Now I want to display only the first 30 from it, and when a "more" button is pressed, 30 more records will appear below them. How can I do it in an iPhone application?
You can use SQL Query to achieve your goal
-(NSMutableArray *)SelectResult:(int)offset
{
NSMutableArray *arrdata;
arrdata=[[NSMutableArray alloc]init];
sqlite3 *database;
NSString *databasePath = [self getDBPath];
if(sqlite3_open([databasePath UTF8String], &database) == SQLITE_OK) {
NSString *sqlQuery=[NSString stringWithFormat:#"Select * from TableName where RecordId > %d and RecordId <=%d",offset,offset+30];
sqlite3_stmt *compiledStatement;
compiledStatement=nil;
if(sqlite3_prepare_v2(database, [sqlQuery UTF8String], -1, &compiledStatement, NULL) == SQLITE_OK)
{
while(sqlite3_step(compiledStatement) == SQLITE_ROW)
{
if ((char *)sqlite3_column_text(compiledStatement,0)!=0)
{
NSMutableDictionary *temData = [[NSMutableDictionary alloc] init];
int pKey = sqlite3_column_int(compiledStatement,0);
[temData setValue:[NSString stringWithFormat:#"%d",pKey] forKey:#"RecordId"];
[arrdata addObject:temData];
}
}
}
sqlite3_finalize(compiledStatement);
}
sqlite3_close(database);
return arrdata;
}
Please call this method and pass offset as integer it will give you 30 recored from the offset
like offset = 0 then 1 to 30
offset = 30 then 31 to 60 etc....
Hope it will help you
Happy coding
Just use a NSMutableArray to hold you data. In your table view datasource make sure it displays an extra cell (with the "More" message) if there are any more records to display.
In didSelectRowAtIndexPath you can then modify the table view's data array by adding additional records from the database.
You can generate your SQL query dynamically based on the size of your data array.
How to add nsmutablearray into the sqlite database table?Can any one help me to code?
You can use :
for (int i = 0; i < [mutArray count]; i++)
{
NSString *string = [mutArray objectAtIndex:i];
// insert query
insert into table_name ('string') values(column_name);
}
Use looping Controls to sort the array and insert each values
Example:
for(int itemIndex = 0; itemIndex < [yourArray count];itemIndex++){
NSString *myname = [yourArray objectAtIndex:itemIndex];
//insert myname to database.
}
To retrieve, you can use the sample below code
if(sqlite3_open([path UTF8String], &dataBase) == SQLITE_OK)
{
NSString *query = [NSString stringWithFormat:#"select name from syncTable where Crc = %d",crc]; const char *sql = [query UTF8String];
sqlite3_stmt *statement;
if (sqlite3_prepare(dataBase, sql, -1, &statement, NULL) == SQLITE_OK)
{
char *name;
unsigned int value;
while(sqlite3_step(statement) == SQLITE_ROW)
{
name = (char *)sqlite3_column_text(statement, 0);
[yourArray addObject:[NSString stringWithUTF8String:name]];
}
sqlite3_finalize(statement);
}
}
Here is a list of tutorials for using sqlite with iphone. Its not a matter of simulator or device. It will work fine with simulator also.
Create your db structure properly and work based on this tutorials.
Or
I'd recommend you to use Core Data if you want you work with databases on iPhone OS.
This tutorial should match your app quite well.
Please ask if any more questions.
i want to select data from the table but those data which has same question id in the questions table and answers table.
Now it selects all the data from answers the code is shown below
+ (void) getAnswers:(NSString*)dbPath{
CereniaAppDelegate *appDelegate = (CereniaAppDelegate *)[[UIApplication sharedApplication] delegate];
if (sqlite3_open([dbPath UTF8String], &database) == SQLITE_OK) {
const char *sql = "select *from answers";
sqlite3_stmt *selectstmt;
if(sqlite3_prepare_v2(database, sql, -1, &selectstmt, NULL) == SQLITE_OK) {
while(sqlite3_step(selectstmt) == SQLITE_ROW) {
NSInteger primaryKey = sqlite3_column_int(selectstmt, 0);
Answers *coffeeObj = [[Answers alloc] initWithPrimaryKey:primaryKey];
coffeeObj.answer_text = [NSString stringWithUTF8String:(char *)sqlite3_column_text(selectstmt, 3)];
NSString*testString=coffeeObj.answer_text;
NSLog(testString);
[appDelegate.answerArray addObject:coffeeObj];
int mycount=[appDelegate.answerArray count];
NSLog(#"This is int of latest %d",mycount);
[coffeeObj release];
}
}
}
else
sqlite3_close(database); //Even though the open call failed, close the database connection to release all the memory.
}
I suggest avoiding c level code for calling a SQLite DB - try a simple wrapper over SQLite - see https://github.com/JohnGoodstadt/EasySQLite
This will allow:
DataTable* result = [_db ExecuteQuery:#"SELECT * FROM answers"];
It feels like you need to use a LEFT JOIN statement to answer your actual query - if you add info about your table definitions and what data you are trying to get out I can help more.
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 try to get a connection my server, with the sqlite3_open command!
my question...is it possible to that? i got the following code...
// Get the path to the documents directory and append the databaseName
databaseName = #"AnimalDatabase.sql";
NSString *serverpath = #"http://localhost/app/";
databasePath = [serverpath stringByAppendingPathComponent:databaseName];
and then this here
-(void) readAnimalsFromDatabase {
// Setup the database object
sqlite3 *database;
// Init the animals Array
animals = [[NSMutableArray alloc] init];
// 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 animals";
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)];
NSString *aDescription = [NSString stringWithUTF8String:(char *)sqlite3_column_text(compiledStatement, 2)];
NSString *aImageUrl = [NSString stringWithUTF8String:(char *)sqlite3_column_text(compiledStatement, 3)];
// Create a new animal object with the data from the database
Animal *animal = [[Animal alloc] initWithName:aName description:aDescription url:aImageUrl];
// Add the animal object to the animals Array
[animals addObject:animal];
[animal release];
}
}
// Release the compiled statement from memory
sqlite3_finalize(compiledStatement);
}
sqlite3_close(database);
}
any suggestion??
Where you get the idea that SQLite can open database from URL??
It can open files only (or, create temporary db in memory).
The answer is just NO, there are lot of mistakes in your code anyway. For example:
databaseName = #"AnimalDatabase.sql";
Where did you get this. iPhone is working with sqlite database, it has nothing in common with sql files:)