Issues when reading from a database in an iPhone app - ios

I am making an iPhone app for a school project that reads and writes to a database. I have managed to get my code to write to it but it won't read. Below is the code I'm using to read:
NSString * paths=[self getWritableDBPath];
const char *dbpath = [paths UTF8String];
sqlite3_stmt *statement;
static sqlite3 *database = nil;
if (sqlite3_open(dbpath, &database) == SQLITE_OK)
{
NSString *querySQL = [NSString stringWithFormat: #"SELECT questionright, totalquestions, FROM results", nil];
const char *query_stmt = [querySQL UTF8String];
if (sqlite3_prepare_v2(database, query_stmt, -1, &statement, NULL) == SQLITE_OK)
{
while(sqlite3_step(statement) == SQLITE_ROW)
{
//code...
}
sqlite3_finalize(statement);
}
sqlite3_close(database);
}
Here is getWritableDBPath:
-(NSString *) getWritableDBPath {
NSString *myDB = #"appData.db";
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory , NSUserDomainMask, YES);
NSString *documentsDir = [paths objectAtIndex:0];
return [documentsDir stringByAppendingPathComponent:myDB];
}
The reason it doesn't work is that the sqlite3_prepare_v2 if statement is never satisfied.
When I write to the database I copy it to documents.
I am quite sure the results table exists as I am able to write to it. Here is the original sql statement:
DROP TABLE IF EXISTS "Questions";
CREATE TABLE "Questions" ("QuestionID" INTEGER PRIMARY KEY NOT NULL , "Question" TEXT, "RightAnswer" TEXT, "WrongAnswer1" TEXT, "WrongAnswer2" TEXT, "Done" BOOL, "Catagory" TEXT, "Audio" INTEGER);
DROP TABLE IF EXISTS "Results";
CREATE TABLE "Results" ("ResultID" INTEGER PRIMARY KEY NOT NULL , "QuestionRight" INTEGER, "TotalQuestions" INTEGER, "Catagory" TEXT);
I did find a similar question on here but didn't think the answers were that relevant to me.
Thanks for your help.

If you want my advice, don't use the sqlite c libraries directly if you don't really need that, you can use FMDB library and get rid of all the c headache
https://github.com/ccgus/fmdb
You can simply do it like this
FMDatabase *db = [FMDatabase databaseWithPath:#"your full db path in documents goes here"];
if (![db open]) {
return;
}
FMResultSet *s = [db executeQuery:#"Your query goes here"];
if ([s next]) {
int totalCount = [s intForColumn:#"totalCount"];
}

Related

Can not read data from the sqlite in iOS

I checked from sqlitebrowser that I successfully created sqlite and inserted data to sqlite, but now my problem is I could not read data from sqlite. I am new to sqlite.
Should I open the sqlite first, and read it? Where is wrong on my code below?
This code for open the existing sqlite.
-(void)openSqlite{
NSString *docsDir = [NSString stringWithFormat:#"Questiondata.db"];
NSArray *dirPaths;
_databasePath = [[NSString alloc] initWithString:[docsDir stringByAppendingPathComponent:#"Questiondata.db"]];
NSFileManager *filemgr = [NSFileManager defaultManager];
if ([filemgr fileExistsAtPath:_databasePath] == NO) {
const char *dbpath = [_databasePath UTF8String];
if (sqlite3_open(dbpath, &_contactDB) == SQLITE_OK) {
char *errorMessage;
const char *sql_statement ="CREATE TABLE IF NOT EXISTS users (ID INTEGER PRIMARY KEY AUTOINCREMENT, NAME TEXT, ADDRESS TEXT, PHONE TEXT)";
if (sqlite3_exec(_contactDB,sql_statement,NULL,NULL,&errorMessage) != SQLITE_OK) {
NSLog(#"Failed to create the table");
}
sqlite3_close(_contactDB);
}
else{
NSLog(#"Fail to open/create the table");
}
}
}
This is code for read data from existing sqlite.
-(void)readData{
NSLog(#"we came here");
sqlite3_stmt *statement;
const char *dbpath = [_databasePath UTF8String];
if (sqlite3_open(dbpath, &_contactDB)) {
NSString *querySQL = [NSString stringWithFormat:#"SELECT * FROM Questions WHERE QuestionNumber = 1"];
const char*query_statement = [querySQL UTF8String];
if (sqlite3_prepare_v2(_contactDB, query_statement, -1, &statement, NULL)== SQLITE_OK) {
if (sqlite3_step(statement) == SQLITE_ROW) {
NSString *addressfield = [[NSString alloc] initWithUTF8String:(const char *) sqlite3_column_text(statement,0)];
NSLog(#"finddata:%#",addressfield);
}else{
NSLog(#"notfinddatabase");
}
sqlite3_finalize(statement);
}else{
NSLog(#"failed to serache database");
}
sqlite3_finalize(statement);
sqlite3_close(_contactDB);
NSLog(#"not be here");
}
}
In openSqlite method
const char *sql_statement ="CREATE TABLE IF NOT EXISTS users (ID INTEGER PRIMARY KEY AUTOINCREMENT, NAME TEXT, ADDRESS TEXT, PHONE TEXT)";
and in your query
NSString *querySQL = [NSString stringWithFormat:#"SELECT * FROM Questions WHERE QuestionNumber = 1"];
table name and column name are not same.
Change in Place "Questions" with "users" .
and also change "QuestionNumber" with the table column.
May be, it will helps you or feel free.
sqlite doesn't report all errors until you start accessing the data. For example just about any filename and path will pass without errors.
First of all you must check that, the database is in the Documents folder?
It's not there by default.
Perhaps it's in the main bundle?
Try this:
NSString *dbName = [[NSBundle mainBundle] pathForResource:#"dbFile" ofType:#"db"];

does it possible to save Db file with application and not by adding in from itunes

I want the application which work online as well as offline example WhatsApp. For that i have to sync data from web service then store it in sqlite db file.
And I want that whoever installs this application would have a slot for automatic saving data in database file. Do I have to add db file from iTunes?
I don't want to use core data concept.
Is it possible it will be there in with application?
Like in Android there is something called cache memory where db file is stored so there is any sort of provision for it in ios?
+(int)insert_In_AdverImage:(NSString *)strid ImageName:(NSString *)strimg Isshow:(NSString *)strshow LastUpdateId:(NSString *)date isdelete:(NSString *)isdelete Sortorder:(int)sortOrder{
sqlite3 *database;
int retValue = 0;
if(sqlite3_open([databasePath UTF8String], &database) == SQLITE_OK) {
NSString *tempSQL = [[NSString alloc] initWithFormat:#"INSERT INTO ADVERIMAGE(advId ,advimg ,isshow ,LastUpdateId ,IsDelete ,SortorderId ) VALUES ('%#', '%#', '%#', '%#', '%#', '%d')", strid, strimg, strshow, date, isdelete, sortOrder];
const char *sqlStatement = [tempSQL cStringUsingEncoding:NSUTF8StringEncoding];
sqlite3_stmt *compiledStatement;
sqlite3_prepare_v2(database, sqlStatement, -1, &compiledStatement, NULL);
sqlite3_step(compiledStatement);
retValue = (int)sqlite3_last_insert_rowid(database);
sqlite3_finalize(compiledStatement);
}
sqlite3_close(database);
return retValue;
}
works well. But still the db file in app bundle is empty.i got it that whenever we insert something it will be inserted in document and if we have to see the inserted data we have to get it from document
Thanks in advance
Any Help would be appreciated.
Yes. Possible.
You can store SQlite DB in your applications's Document Directory. You need to write your own Query to Open DB, Insert Data, Retrieve Data from DB.
Check out following tutorial for your requirement : http://www.appcoda.com/sqlite-database-ios-app-tutorial/
Hope it helps.
Following function is used to Insert :
NSArray *docsDirectory = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *docPath = [docsDirectory objectAtIndex:0];
NSString *databasePath = [docPath stringByAppendingPathComponent:#"Database.sqlite"];
sqlite3 *dbHandler;
const char *dbPath = [databasePath UTF8String];
sqlite3_stmt *sqlStmt;
if(sqlite3_open(dbPath, &dbHandler) == SQLITE_OK)
{
if (sqlite3_prepare_v2(dbHandler, [queryString UTF8String], -1, &sqlStmt, NULL) == SQLITE_OK)
{
if (sqlite3_step(sqlStmt) == SQLITE_DONE)
{
NSLog(#"Data Inserted");
}
else
{
NSLog(#"Not inserted");
}
}
else
{
NSLog(#"Failed to Insert data -InsertDataFunc");
}
sqlite3_close(dbHandler);
}

How to view the content of .db file?

I am using Xcode 6.4, developing apps for iOS 8 that need to use database. I inserted some information into my database ("something.db" file). I want to see the content of "something.db" to see what I inserted. How can I view its content?
This is my code for creating the database "company.db" and table "Staff"(ID PK, NAME TEXT, AGE INTEGER):
-(void) createOrOpenDB {
NSArray *path = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *docPath = [path objectAtIndex:0];
dbPathString = [docPath stringByAppendingPathComponent:#"company.db"];
char *error;
NSFileManager *fileManager = [NSFileManager defaultManager];
if(![fileManager fileExistsAtPath:dbPathString]) {
const char *dbPath =[dbPathString UTF8String];
if(sqlite3_open(dbPath, &personDB)==SQLITE_OK) {
const char *sql_stmt = "CREATE TABLE IF NOT EXISTS Staff (ID INTEGER PRIMARY KEY AUTOINCREMENT, NAME TEXT, AGE INTEGER)";
sqlite3_exec(personDB, sql_stmt, NULL, NULL, &error);
sqlite3_close(personDB);
}
}
}
This is my code for inserting information into the table "Staff":
- (IBAction)addPersonButton:(id)sender {
char *error;
if(sqlite3_open([dbPathString UTF8String], &personDB) == SQLITE_OK) {
NSString *insertStmt = [NSString stringWithFormat:#"INSERT INTO Staff (NAME, AGE) values ('%s', '%d')", [self.nameField.text UTF8String], [self.ageField.text intValue]];
const char *insert_stmt = [insertStmt UTF8String];
if(sqlite3_exec(personDB, insert_stmt, NULL, NULL, &error) == SQLITE_OK) {
NSLog(#"Person added");
Person *person = [[Person alloc] init];
[person setName:self.nameField.text];
[person setAge:[self.ageField.text intValue]];
[arrayofPerson addObject:person];
}
sqlite3_close(personDB);
}
}
The code works well because I was able to display the information of the "Staff" table in the tableview. But how to view that information in the .db file?
p/s: I changed it to "something.xls" but Excel does not display human readable information. I also downloaded Fileviewpro but did not know how to use. Someone helps me please!
Thank you very much!
You can use any app that is designed to view the contents of an sqlite file. for example: http://sqlitebrowser.org
If you are running on simulator you can use ~/Library/Developer/CoreSimulator/Devices/1A8DF360-B0A6-4815-95F3-68A6AB0BCC78/data/Container/Data/Application/
to get to the simulator just replace the long UDID with your device.

unable to update or insert a row in a table

I want to update a row in my iPhone app. Below is the code. It shows in my log that query is executed and row has been updated, but when I excess that table, it seems to be empty. And also it always updates a row even if I am trying to enter a row with new id, it should insert instead of updating in this case.
//create local database
NSString *docsDir = NULL;
NSArray *dirPaths = NULL;
sqlite3 *localDB = NULL;
// Get the documents directory
dirPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
docsDir = [dirPaths objectAtIndex:0];
// Build the path to the database file
NSString *databasePath = [[NSString alloc] initWithString: [docsDir stringByAppendingPathComponent: #"localscentsy1.db"]];
NSLog(#"%#",databasePath);
const char *dbpath = [databasePath UTF8String];
sqlite3_stmt *statement = NULL;
if (sqlite3_open(dbpath, &localDB) == SQLITE_OK)
{
NSString *updateSQL = [NSString stringWithFormat:#"UPDATE Ratings set rating = '%d' WHERE perfume_id = ?",
(int)rating];
const char *update_stmt = [updateSQL UTF8String];
if(sqlite3_prepare_v2(localDB, update_stmt, -1, &statement, NULL ) ==SQLITE_OK){
sqlite3_bind_int(statement, 1, tappedItem.perfumeId);
}
char* errmsg;
sqlite3_exec(localDB, "COMMIT", NULL, NULL, &errmsg);
if(SQLITE_DONE != sqlite3_step(statement)){
NSLog(#"Error while updating. %s", sqlite3_errmsg(localDB));
NSLog(#"query failed: %s", sqlite3_errmsg(localDB));
NSLog(#"%#",#"update unsuccessfull");
NSLog(#"New data, Insert Please");
sqlite3_stmt *statement2 = NULL;
NSString *insertSQL = [NSString stringWithFormat:
#"INSERT INTO Ratings (perfume_id,rating) VALUES (\"%d\",\"%d\")",
tappedItem.perfumeId,
(int)rating];
const char *insert_stmt = [insertSQL UTF8String];
sqlite3_prepare_v2(localDB, insert_stmt, -1, &statement2, NULL);
if (sqlite3_step(statement2) == SQLITE_DONE)
{
NSLog(#"New data, Inserted");
}
sqlite3_finalize(statement2);
}
else{
NSLog(#"%#",#"update successfull");
sqlite3_finalize(statement);
}
sqlite3_close(localDB);
}
Any help will be appreciated. I am new at ios development and this code is taking so much of my time. Here is my log which always says "update successful"
CyberGenies/Library/Application Support/iPhone Simulator/7.0/Applications/24D2FEE2- DBE6-441A-AC79-1F2D57F96C88/Documents/localscentsy1.db
2014-07-27 01:03:26.612 Scentsy Squirrel[19008:a0b] update successfull
Have you seen if the db really has the structure? Some times when you start doing queries in an empty db (I mean not even tables) the query itself build the structure you are giving it on the query. You can check by compiling on the simulator and look for the db in the Mac finder.

How to iterate through sqlite_step result

Could someone be so kind as to fill in the few missing pieces of code below. I am struggling with executing an sqlite statement using sqlite3_step, iterating through each row of results and putting the data into a useable format.
Here is the code that creates the database (Database is only two colums)
// Check if database is setup, if not create it
NSString *documents_directory;
NSArray *directory_path;
// Get the documents directory
directory_path = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
documents_directory = [directory_path objectAtIndex:0];
// Build the path to the database file
databasePath = [[NSString alloc] initWithString: [documents_directory stringByAppendingPathComponent: #"weights.db"]];
NSFileManager *file_manager = [NSFileManager defaultManager];
// Create database if it doesn't already exist
if([file_manager fileExistsAtPath: databasePath ] == NO){
const char *database_path = [databasePath UTF8String];
if(sqlite3_open(database_path, &contactDB) == SQLITE_OK){
char *error_message;
const char *sql_statement = "CREATE TABLE IF NOT EXISTS RECORDED_WEIGHTS (ID INTEGER PRIMARY KEY AUTOINCREMENT, WEIGHT TEXT, TIME TEXT)";
if(sqlite3_exec(contactDB, sql_statement, NULL, NULL, &error_message) != SQLITE_OK){
status.text = #"Failed to create table";
}
sqlite3_close(contactDB);
}else{
status.text = #"Failed to open/create database";
}
}
And here is the code I am trying to complete;
// Get info from database and load it.
const char *database_path = [databasePath UTF8String];
sqlite3_stmt *statement;
if(sqlite3_open(database_path, &contactDB) == SQLITE_OK){
NSString *SQLquery = [NSString stringWithFormat:#"SELECT * FROM RECORDED_WEIGHTS ORDER BY TIME DESC"];
const char *query_statement = [SQLquery UTF8String];
if(sqlite3_prepare_v2(contactDB, query_statement, -1, &statement, NULL) == SQLITE_OK){
// Please help me execute statement and get results into useable format here.
}
sqlite3_finalize(statement);
}
sqlite3_close(contactDB);
Thanks in advance.
You want to do something like this:
while(sqlite3_step(statement) == SQLITE_ROW)
{
// int value
int intValue = sqlite3_column_int(statement,fieldIndex);
// string value
NSString* stringValue;
if (sqlite3_column_type(dbps, fieldIndex) != SQLITE_NULL)
{
const char *c = (const char *)sqlite3_column_text(dbps, fieldIndex);
if (c)
{
stringValue = #(c);
}
}
... etc...
}
Look at the documents for the different column types. You can also look at different objective-c wrappers out there to get an idea of how to access the database.

Resources