I am trying to sort / order SQL data in my iOS app. the database is working fine. i can add data, display in tableview, edit, delete everything is working fine. just can't sort. below is the code i am using.
-(void)sortTable
{
//CHECKING DIRECTORY AND CREATING DATABASE CODE STARTS
NSString *docsDir;
NSArray *dirPaths;
// Get the documents directory
dirPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
docsDir = dirPaths [0];
//Build the path to the database file
_databasePath = [[NSString alloc]initWithString:[docsDir stringByAppendingPathComponent:#"events.db"]];
NSFileManager *filemgr = [NSFileManager defaultManager];
if ([filemgr fileExistsAtPath: _databasePath] == NO)
{
const char *dbpath = [_databasePath UTF8String];
if (sqlite3_open(dbpath, &_eventDB) == SQLITE_OK)
{
char *errMsg;
const char *sql_stmt =
"CREATE TABLE IF NOT EXISTS EVENTS (ID INTEGER PRIMARY KEY AUTOINCREMENT, EVENT TEXT, EVENTDATE TEXT)";
//closing database after creating
if (sqlite3_exec(_eventDB, sql_stmt, NULL, NULL, &errMsg) !=SQLITE_OK)
{
// sqlite3_close(_eventDB);
}
}
}
//CHECKING DIRECTORY AND CREATING DATABASE CODE ENDS
//sort sql table
sqlite3_stmt *statement;
const char *dbpath = [_databasePath UTF8String];
if (sqlite3_open(dbpath, &_eventDB) == SQLITE_OK)
{
NSString *sortSQLTable = [NSString stringWithFormat:#"SELECT EVENT FROM EVENTS ORDER BY EVENT"]; // EVENTS is the table name and EVENT is the column.
const char *sort_stmt = [sortSQLTable UTF8String];
sqlite3_prepare_v2(_eventDB, sort_stmt, -1, &statement, NULL);
}
}
I am executing this void statement in viewDidLoad.
I have searched a lot. tried different things. just could not make it work. can someone help please.
UPDATE:
I just found that the ORDER BY query is actually sorting the table, but its not saving the database.
any idea how i can save the database after sorting?
If you are looking to sort data to display on your tableview you could use a NSSortDescriptor.
Here is the documentation from Apple on how to use them.
The gist though is something like ..
//array of People objects with properties of firstName and lastName just for example
NSArray *firstNames = #[ #"Jan", #"Steve", #"Jay", #"Mike" ];
NSArray *lastNames = #[ #"Joker", #"Jones", #"Smith", #"Pham" ];
NSMutableArray *people = [NSMutableArray array];
[firstNames enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
Person *person = [[Person alloc] init];
person.firstName = [firstNames objectAtIndex:idx];
person.lastName = [lastNames objectAtIndex:idx];
[people addObject:person];
}];
//make the descriptor
NSSortDescriptor *firstNameSortDescriptor = [NSSortDescriptor sortDescriptorWithKey:#"firstName"
ascending:YES ];
//sort the array using the descriptor
NSLog(#"By first name: %#", [people sortedArrayUsingDescriptors:#[firstNameSortDescriptor]]);
Related
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.
My table in SQLITE is in the following format.
id name date height
1 tt 12-2-15 120
2 ss 15-3-15 110
3 tt 14-5-15 120
....
10 tt 19-6-15 130
(1)I like to get all rows under name tt in one instruction, then put into two dimensional array. How can i implement it?
(2)How to delete all rows under name tt in one instruction?
My code is in iOS. I couldn't find solution easily.
EDIT:
Just to share what I implement.
NSString *databasePath;
NSString *docsDir;
NSArray *dirPaths;
//Database
dirPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
docsDir = [dirPaths objectAtIndex:0];
// Build the path to the database file
databasePath = [[NSString alloc]initWithString:[docsDir stringByAppendingPathComponent: #"RECORDS.db"]];
const char *dbpath = [databasePath UTF8String];
if (sqlite3_open(dbpath,& RECORDS) == SQLITE_OK)
{
retval = [[NSMutableArray alloc] init];
NSString *query = [NSString stringWithFormat:#"SELECT id, nameid, date, height FROM RECORD WHERE nameid=\"%#\"", currentNameID];
const char *query_stmt = [query UTF8String];
if (sqlite3_prepare_v2(RECORDS, query_stmt, -1, &statement, nil) == SQLITE_OK) {
while (sqlite3_step(statement) == SQLITE_ROW) {
char *date = (char *) sqlite3_column_text(statement, 1);
int height = (int) sqlite3_column_text(statement, 2);
NSString *name = [[NSString alloc] initWithUTF8String:date];
HeightInfo *info = [[HeightInfo alloc] initWithInfos:name withheight:(int)height];
[retval addObject:info];
}
sqlite3_finalize(statement);
sqlite3_close(RECORDS);
}
}
Thanks
Do you need help with the SQL or the ios framework?
The SQL is pretty straightforward;
select id, name, date, height from mytablename where name = "tt";
delete from mytablename where name == "tt";
Practice the commands on the command line so you see how they work.
For processing your data look at the great examples by Ray Wenderlich;
http://www.raywenderlich.com/913/sqlite-tutorial-for-ios-making-our-app
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"];
}
hi i'm getting stuck with some code. i have a file catalog.db and a class that let me work with it. When i try to retrieve datas from the db it seems like it's empty. With several nslog i can see that it connect and enter the database, i can see it enter in it but then it won't get any value from it.
i tried to see if the query was wrong with an external DB manager software and the query works fine...
this is my class
#import "DBAccess.h"
sqlite3* database;
#implementation DBAccess
-(id)init{
self = [super init];
if (self){
[self initializeDatabase];
}
return self;
}
-(void)initializeDatabase{
NSString *path = [[NSBundle mainBundle]pathForResource:#"catalog" ofType:#"db"];
if (sqlite3_open([path UTF8String], &database) == SQLITE_OK) { NSLog(#"Opening Database"); }
else {
sqlite3_close(database);
NSAssert1(0, #"FAILED to open database '%s'", sqlite3_errmsg(database));
}
}
-(void)closeDatabase{
if (sqlite3_close(database) != SQLITE_OK){
NSAssert1(0, #"ERROR to close databse: '%s'", sqlite3_errmsg(database));
}
}
-(NSMutableArray *)getAllProduct{
NSMutableArray *products = [[NSMutableArray alloc]init];
const char *sql = "SELECT product.ID,product.Name, Manufacturer.name, product.details,product.price, product.quantityOnHand,country.country,product.image FROM product,manufacturer,country WHERE manufacturer.manufacturerID = product.manufacturerID and product.countryOfOriginID = country.countryID";
sqlite3_stmt *statement;
int sqlResult = sqlite3_prepare_v2(database, sql, -1, &statement, NULL);
NSLog(#"sqlResult: %d", sqlResult);
if (sqlResult == SQLITE_OK){
NSLog(#"sql step statement: %d",sqlite3_step(statement));
NSLog(#"QUERY DONE");
while (sqlite3_step(statement) == SQLITE_ROW){
NSLog(#"TEST");
Product *product = [[Product alloc]init];
char *name = (char *)sqlite3_column_text(statement, 1);
NSLog(#"n %s",name);
char *manufacturer = (char *)sqlite3_column_text(statement, 2);
NSLog(#"m %s", manufacturer);
char *details = (char *)sqlite3_column_text(statement, 3);
NSLog(#"d %s", details);
char *countryoforigin = (char *)sqlite3_column_text(statement, 6);
NSLog(#"%s", countryoforigin);
char *image = (char *)sqlite3_column_text(statement, 7);
NSLog(#"%s", image);
product.ID = sqlite3_column_text(statement, 0);
product.name = (name)?[NSString stringWithUTF8String:name]:#"";
product.manufacturer = (manufacturer)?[NSString stringWithUTF8String:manufacturer]:#"";
product.details = (details)?[NSString stringWithUTF8String:details]:#"";
product.price = sqlite3_column_double (statement, 4);
product.quantity = sqlite3_column_int(statement, 5);
product.countryOfOrigin = (countryoforigin)?[NSString stringWithUTF8String:countryoforigin]:#"";
product.image = (image)?[NSString stringWithUTF8String:image]:#"";
[products addObject:product];
}
sqlite3_finalize(statement);
}
else {
NSLog(#"Problem with database %d",sqlResult);
}
return products;
}
#end
this is what i get in my console
2013-08-14 12:38:58.505 Catalog[1642:c07] Opening Database
2013-08-14 12:38:58.508 Catalog[1642:c07] sqlResult: 0
2013-08-14 12:38:58.509 Catalog[1642:c07] sql step statement: 101
2013-08-14 12:38:58.509 Catalog[1642:c07] QUERY DONE
2013-08-14 12:38:58.510 Catalog[1642:c07] ()
what can be my problem? thanks
Here
NSLog(#"sql step statement: %d",sqlite3_step(statement));
you fetch already the first row (without using the result).
1)Copy the database to your documents directory...
-(void) checkAndCreateDatabase{
// Check if the SQL database has already been saved to the users phone, if not then copy it over
NSArray *documentPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDir = [documentPaths objectAtIndex:0];
NSString *databasePath = [documentsDir stringByAppendingPathComponent:#"test.sqlite"];
BOOL success;
// Create a FileManager object, we will use this to check the status
// of the database and to copy it over if required
NSFileManager *fileManager = [NSFileManager defaultManager];
// Check if the database has already been created in the users filesystem
success = [fileManager fileExistsAtPath:databasePath];
// If the database already exists then return without doing anything
if(success) return;
// If not then proceed to copy the database from the application to the users filesystem
// Get the path to the database in the application package
NSString *databasePathFromApp = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:#"test.sqlite"];
// Copy the database from the package to the users filesystem
[fileManager copyItemAtPath:databasePathFromApp toPath:databasePath error:nil];
}
2)Then talk to database in this way.
-(void)sqliteTransaction
{
sqlite3 *database;
NSArray *documentPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDir = [documentPaths objectAtIndex:0];
NSString *databasePath = [documentsDir stringByAppendingPathComponent:#"test.sqlite"];
// Init the animals Array
// 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 me";
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)];
NSLog(#"%#",aName);
// Create a new animal object with the data from the database
}
}
// Release the compiled statement from memory
sqlite3_finalize(compiledStatement);
}
sqlite3_close(database);
}
Try like this, before going to SELECT make sure the table is properly connected for selection with the open query like this
sqlite3_open(dbpath, &ProDB)
After that execute your selection. See this below sample code. Hope it will help
ex:
NSMutableArray *sessionDetails = [NSMutableArray array];
NSString *docsDir;
NSArray *dirPaths;
dirPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
docsDir = [dirPaths objectAtIndex:0];
NSString *databasePath = [[NSString alloc] initWithString: [docsDir stringByAppendingPathComponent: #"cPro.db"]];
const char *dbpath = [databasePath UTF8String];
sqlite3_stmt *statement;
if (sqlite3_open(dbpath, &ProDB) == SQLITE_OK)
{
NSString *querySQL = [NSString stringWithFormat: #"SELECT * FROM USER_SESSION_INFO"];
NSLog(#"query: %#",querySQL);
const char *query_stmt = [querySQL UTF8String];
if (sqlite3_prepare_v2(ProDB, query_stmt, -1, &statement, NULL) == SQLITE_OK)
{
while(sqlite3_step(statement) == SQLITE_ROW)
{
// Your functionality.
}
}
}
i tried the method you guys suggested but i still get the same problem.
i think i found out what's causing it.
i changed my query with this:
const char *sql = "SELECT product.ID,product.Name, product.details,product.price, product.quantityOnHand,product.image FROM Product";
and this way it works... so it looks like i have trouble reading other tables...
the moment i add another table it stop working. but that's weird cause with external db manager software the query works just fine
Well following this tutorial I have some problems in inserting values to my DB although everything seems to be working fine.
This is my code for inserting entries.
-(void)insertOrder:(MyOrderList*)entry
{
// Create insert statement for the person
NSString *insertStatement = [NSString stringWithFormat:#"INSERT INTO LIST (URL, CODE, EMAIL, FULL) VALUES (\"%#\", \"%#\", \"%#\",\"%#\")", entry.db_url, entry.db_code, entry.db_email,entry.db_full];
NSLog(#"SQL INSERTION COMMAND:%#",insertStatement);
char *error;
if ( sqlite3_exec(databaseHandle, [insertStatement UTF8String], NULL, NULL, &error) == SQLITE_OK)
{
NSLog(#"Order inserted.");
}
else
{
NSLog(#"Error: %s", error);
}
}
And I can see "Order Inserted" being printed out.
This is my code for retrieving the list.
-(NSArray*) getList
{
NSMutableArray *persons = [[NSMutableArray alloc]init];
NSString *queryStatement = [NSString stringWithFormat:#"SELECT URL,CODE ,MAIL, FULL FROM LIST"];
sqlite3_stmt *statement;
NSLog(#"Query:%#",queryStatement);
if (sqlite3_prepare_v2(databaseHandle, [queryStatement UTF8String], -1, &statement, NULL) == SQLITE_OK)
{
// Iterate over all returned rows
while (sqlite3_step(statement) == SQLITE_ROW) {
NSLog(#"Url of my List is:%#",[NSString stringWithUTF8String:(char*)sqlite3_column_text(statement, 0)]);
MyOrderList *person = [[MyOrderList alloc]initWithUrl:[NSString stringWithUTF8String:(char*)sqlite3_column_text(statement, 0)] andCode:[NSString stringWithUTF8String:(char*)sqlite3_column_text(statement, 1)] andEmail:[NSString stringWithUTF8String:(char*)sqlite3_column_text(statement, 2)] andFull:[NSString stringWithUTF8String:(char*)sqlite3_column_text(statement, 3)]];
[persons addObject:person];
// Release the person because the array takes ownership
//[person release];
}
sqlite3_finalize(statement);
}
//return [persons autorelease];
return persons;
}
and this is how I use it in my .m file
DataController *dataController = [[DataController alloc]init];
[dataController initDatabase];
//[dataController release];
MyOrderList *order = [[MyOrderList alloc] initWithUrl:url_2 andCode:keycode andEmail:mail andFull:full_2 ];
[dataController insertOrder:order];
//data has been added
NSMutableArray* persons = [dataController getList];
and I see that persons are 0.
From terminal I see this:
Admins-MacBook-Air:~ admin$ sqlite3 Users/admin/Library/Application\ Support/iPhone\ Simulator/5.1/Applications/1A70F53B-133E-46AE-833E-13F205EA96EA/Documents/sqlite.db
SQLite version 3.7.12 2012-04-03 19:43:07
Enter ".help" for instructions
Enter SQL statements terminated with a ";"
sqlite> .schema
Error: unable to open database "Users/admin/Library/Application Support/iPhone Simulator/5.1/Applications/1A70F53B-133E-46AE-833E-13F205EA96EA/Documents/sqlite.db": unable to open database file
Admins-MacBook-Air:~ admin$
it's like my db is not even created.
this is my code for creating the DB.
-(void)initDatabase
{
// Create a string containing the full path to the sqlite.db inside the documents folder
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *databasePath = [documentsDirectory stringByAppendingPathComponent:#"sqlite.db"];
NSLog(#"Path is:%#",databasePath);
// Check to see if the database file already exists
bool databaseAlreadyExists = [[NSFileManager defaultManager] fileExistsAtPath:databasePath];
// Open the database and store the handle as a data member
if (sqlite3_open([databasePath UTF8String], &databaseHandle) == SQLITE_OK)
{
// Create the database if it doesn't yet exists in the file system
if (!databaseAlreadyExists)
{
// Create the PERSON table
const char *sqlStatement = "CREATE TABLE IF NOT EXISTS LIST (ID INTEGER PRIMARY KEY AUTOINCREMENT, URL TEXT, CODE TEXT, EMAIL TEXT, FULL TEXT)";
char *error;
if (sqlite3_exec(databaseHandle, sqlStatement, NULL, NULL, &error) == SQLITE_OK)
{
NSLog(#"Database and tables created.");
}
else
{
NSLog(#"Error: %s", error);
}
}
}
}