How to read one column from SQLite and store in Array - ios

I have SQLite database with 5 columns named: Name, ID, ChildID, ParentID, BrotherID.
In this database I have many records and I want to store one of all columns value in array and return this array. For example I want to get all value in ParentID column. I use this query code:
Select ParentID from Table1 (Table1 is name of table)
This is my code for get array from certain column :
/*==================================================================
METHOD FOR GETTING MIDIFIED FROM DATABASE
==================================================================*/
- (NSMutableArray*)readingModified
{
ModiArray = [[NSMutableArray alloc] init];
// Setup the database object
sqlite3 *database2;
// Open the database from the users filessytem
if(sqlite3_open([[self DatabaseSqlite] UTF8String], &database2) == SQLITE_OK)
{
// Setup the SQL Statement and compile it for faster access
//SQLIte Statement
NSString *sqlStatement_userInfo =[NSString stringWithFormat:#"Select ParentID from Table1"];
sqlite3_stmt *compiledStatement;
if(sqlite3_prepare_v2(database2, [sqlStatement_userInfo UTF8String], -1, &compiledStatement, NULL) == SQLITE_OK)
{
// Loop through the results and add them to the feeds array
while(sqlite3_step(compiledStatement) == SQLITE_ROW)
{
// Init the Data Dictionary
NSMutableDictionary *_dataDictionary2=[[NSMutableDictionary alloc] init];
NSString *_recordParentID = [NSString stringWithUTF8String:(char *)sqlite3_column_text(compiledStatement, 0)];
[_dataDictionary2 setObject:[NSString stringWithFormat:#"%#",_recordModified] forKey:#"ParentID"];
[array addObject:_dataDictionary2];
}
}
else
{
NSLog(#"No Data Found");
}
// Release the compiled statement from memory
sqlite3_finalize(compiledStatement);
}
sqlite3_close(database2);
return ModiArray;
}
please tell me my mistake.

my friend a few be careful.
this code is right but in line you mistake :
[array addObject:_dataDictionary2];
instead array put ModiArray
/*==================================================================
METHOD FOR GETTING MIDIFIED FROM DATABASE
==================================================================*/
- (NSMutableArray*)readingModified
{
ModiArray = [[NSMutableArray alloc] init];
// Setup the database object
sqlite3 *database2;
// Open the database from the users filessytem
if(sqlite3_open([[self DatabaseSqlite] UTF8String], &database2) == SQLITE_OK)
{
// Setup the SQL Statement and compile it for faster access
//SQLIte Statement
NSString *sqlStatement_userInfo =[NSString stringWithFormat:#"Select ParentID from Table1"];
sqlite3_stmt *compiledStatement;
if(sqlite3_prepare_v2(database2, [sqlStatement_userInfo UTF8String], -1, &compiledStatement, NULL) == SQLITE_OK)
{
// Loop through the results and add them to the feeds array
while(sqlite3_step(compiledStatement) == SQLITE_ROW)
{
// Init the Data Dictionary
NSMutableDictionary *_dataDictionary2=[[NSMutableDictionary alloc] init];
NSString *_recordParentID = [NSString stringWithUTF8String:(char *)sqlite3_column_text(compiledStatement, 0)];
[_dataDictionary2 setObject:[NSString stringWithFormat:#"%#",_recordModified] forKey:#"ParentID"];
[ModiArray addObject:_dataDictionary2];
}
}
else
{
NSLog(#"No Data Found");
}
// Release the compiled statement from memory
sqlite3_finalize(compiledStatement);
}
sqlite3_close(database2);
return ModiArray;
}

You are adding object to array and allocating and returning ModiArray.

Related

iOS objective c data is not saving in sqlite3 database

[[NSString alloc]initWithString:[self.documentsDirectory stringByAppendingPathComponent:#"cartdb.sql"]];
Data is not saving in sqlite3 database. BOOL openDatabaseResult is showing no and sqlite3 database is showing null
The query :
query = [NSString stringWithFormat:#"insert into cartProductInfo(null, '%#', '%#', %d)", self.information.text, #"productid", [self.priceDisplayLabel.text intValue]
The code of db
-(void)runQuery:(const char *)query isQueryExecutable:(BOOL)queryExecutable{
// Create a sqlite object.
sqlite3 *sqlite3Database;
// Set the database file path.
NSString *databasePath = [[NSString alloc]initWithString:[self.documentsDirectory stringByAppendingPathComponent:#"cartdb.sql"]];
// Initialize the results array.
if (self.arrResults != nil) {
[self.arrResults removeAllObjects];
self.arrResults = nil;
}
self.arrResults = [[NSMutableArray alloc] init];
// Initialize the column names array.
if (self.arrColumnNames != nil) {
[self.arrColumnNames removeAllObjects];
self.arrColumnNames = nil;
}
self.arrColumnNames = [[NSMutableArray alloc] init];
// Open the database.
BOOL openDatabaseResult = sqlite3_open([databasePath UTF8String], &sqlite3Database);
if(openDatabaseResult == SQLITE_OK) {
// Declare a sqlite3_stmt object in which will be stored the query after having been compiled into a SQLite statement.
sqlite3_stmt *compiledStatement;
// Load all data from database to memory.
BOOL prepareStatementResult = sqlite3_prepare_v2(sqlite3Database, query, -1, &compiledStatement, NULL);
if(prepareStatementResult == SQLITE_OK) {
// Check if the query is non-executable.
if (!queryExecutable){
// In this case data must be loaded from the database.
// Declare an array to keep the data for each fetched row.
NSMutableArray *arrDataRow;
// Loop through the results and add them to the results array row by row.
while(sqlite3_step(compiledStatement) == SQLITE_ROW) {
// Initialize the mutable array that will contain the data of a fetched row.
arrDataRow = [[NSMutableArray alloc] init];
// Get the total number of columns.
int totalColumns = sqlite3_column_count(compiledStatement);
// Go through all columns and fetch each column data.
for (int i=0; i<totalColumns; i++){
// Convert the column data to text (characters).
char *dbDataAsChars = (char *)sqlite3_column_text(compiledStatement, i);
// If there are contents in the currenct column (field) then add them to the current row array.
if (dbDataAsChars != NULL) {
// Convert the characters to string.
[arrDataRow addObject:[NSString stringWithUTF8String:dbDataAsChars]];
}
// Keep the current column name.
if (self.arrColumnNames.count != totalColumns) {
dbDataAsChars = (char *)sqlite3_column_name(compiledStatement, i);
[self.arrColumnNames addObject:[NSString stringWithUTF8String:dbDataAsChars]];
}
}
// Store each fetched data row in the results array, but first check if there is actually data.
if (arrDataRow.count > 0) {
[self.arrResults addObject:arrDataRow];
}
}
}
else {
// This is the case of an executable query (insert, update, ...).
// Execute the query.
BOOL executeQueryResults = sqlite3_step(compiledStatement);
if (executeQueryResults == SQLITE_DONE) {
// Keep the affected rows.
self.affectedRows = sqlite3_changes(sqlite3Database);
// Keep the last inserted row ID.
self.lastInsertedRowID = sqlite3_last_insert_rowid(sqlite3Database);
}
else {
// If could not execute the query show the error message on the debugger.
NSLog(#"DB Error: %s", sqlite3_errmsg(sqlite3Database));
}
}
}
else {
// In the database cannot be opened then show the error message on the debugger.
NSLog(#"%s", sqlite3_errmsg(sqlite3Database));
}
// Release the compiled statement from memory.
sqlite3_finalize(compiledStatement);
}
// Close the database.
sqlite3_close(sqlite3Database);
}

Retrieve data from sqlite

I try to retrieve data from sqlite. Unfortunately the table is filled with null values.
The console shows FIRST ID RECUPERÉ : (null). Can you give me your opinions please?
This is the code:
NSString * statementID = [NSString stringWithFormat:#"SELECT id_message FROM messages;"];
const char * sql_stmt_id = [statementID UTF8String];
sqlite3_stmt *compiledStatement;
if(sqlite3_prepare_v2(contactDB, sql_stmt_id, -1, &compiledStatement, NULL) == SQLITE_OK)
{
[tableauMsgReceived removeAllObjects];
while(sqlite3_step(compiledStatement) == SQLITE_ROW)
{
[tableauMsgReceived addObject:[NSString stringWithFormat:#"%s",(char *) sqlite3_column_text(compiledStatement, 0)]];
NSLog(#"First ID : %#", [tableauMsgReceived objectAtIndex:0]);
}
}
sqlite3_finalize(compiledStatement);
}
sqlite3_close(contactDB);
The only way that the NSLog statement will give that result given your code is if tableauMsgReceived is nil.
Somewhere you need to do:
tableauMsgReceived = [[NSMutableArray alloc] init];
First of all, make sure you have done something like
tableauMsgReceived = [[NSMutableArray alloc] init];
Then, check whether database opened successfully
if (sqlite3_open([YourDBPath UTF8String], &yourDatabase) == SQLITE_OK){}
Last thing, maybe you can try
[tableauMsgReceived addObject:[NSString stringWithUTF8String:(const char *)sqlite3_column_text(statement, 0)]];

How to retrieve value from SQLite database

I'm trying to get data from my DB but I have some problem.
Here is my code:
NSString *action=[[NSString alloc]init];
NSString *queryStatement = [NSString stringWithFormat:#"SELECT ACTIONNAME FROM ACTIONS WHERE ACTIONSYMBOL = '%#'", symbol];
// Prepare the query for execution
sqlite3_stmt *statement;
if (sqlite3_prepare_v2(database, [queryStatement UTF8String], -1, &statement, NULL) == SQLITE_OK)
{
// Create a new address from the found row
while (sqlite3_step(statement) == SQLITE_ROW) {
action = [NSString stringWithUTF8String:(char*)sqlite3_column_text(statement, 1)]; // fails on this line
}
sqlite3_finalize(statement);
return action;
}
(the parameter symbol come from outside)
When I run this, it fails at the line with the call to stringWithUTF8String with sqlite3_column_text results.
You probably want to collect the results in an NSMutableArray:
NSMutableArray *action = [[NSMutableArray alloc] init];
...
while (sqlite3_step(statement) == SQLITE_ROW) {
[action addObject:[NSString stringWithUTF8String:(char*)sqlite3_column_text(statement, 0)]];
}
...
You can then see what was collected later:
for (NSString *s in action) {
NSLog(#"%#", s);
}
EDIT As pointed out in #Rob's answer, the first column is 0, not 1.
In your call to sqlite3_column_text, you're using the index 1, but it takes a zero-based index. Use 0 instead of 1. See the SQLite sqlite_column_XXX documentation, which says:
The leftmost column of the result set has the index 0.
By the way, since stringWithUTF8String throws an exception if you pass it a NULL value, it's often safer to check the result if sqlite3_column_text is not NULL before proceeding, and handle the error gracefully otherwise. Also, you might want to check for sqlite3_step and sqlite3_prepare_v2 errors, like so:
NSString *queryStatement = [NSString stringWithFormat:#"SELECT ACTIONNAME FROM ACTIONS WHERE ACTIONSYMBOL = '%#'", symbol]; // note, it can be dangerous to use `stringWithFormat` to build SQL; better to use `?` placeholders in your SQL and then use `sqlite3_bind_text` to bind the `symbol` value with the `?` placeholder
if (sqlite3_prepare_v2(database, [queryStatement UTF8String], -1, &statement, NULL) == SQLITE_OK)
{
int rc;
while ((rc = sqlite3_step(statement)) == SQLITE_ROW) {
const unsigned char *value = sqlite3_column_text(statement, 0); // use zero
if (value) {
NSString *action = [NSString stringWithUTF8String:(const char *)value];
// now do whatever you want with `action`, e.g. add it to an array or what
} else {
// handle the error (or NULL value) gracefully here
}
// make sure to check for errors in `sqlite3_step`
if (rc != SQLITE_DONE)
{
NSLog(#"%s: sqlite3_step failed: %s", __FUNCTION__, sqlite3_errmsg(database));
}
}
}
else
{
NSLog(#"%s: sqlite3_prepare_v2 failed: %s", __FUNCTION__, sqlite3_errmsg(database));
}
Incidentally, as the above illustrates, to correctly perform all of the error checking is a little cumbersome. This is where FMDB can be useful, simplifying the above to (where db is an FMDatabase object that has been opened):
FMResultSet *rs = [db executeQuery:#"SELECT ACTIONNAME FROM ACTIONS WHERE ACTIONSYMBOL = ?", symbol];
if (!rs) {
NSLog(#"%s: executeQuery failed: %#", __FUNCTION__, [db lastErrorMessage]);
return;
}
while ([rs next]) {
NSString *action = [rs stringForColumnIndex:0];
// do whatever you want with `action` here
}
[rs close];
And if you use ? placeholders (rather than using stringWithFormat to build your SQL, which is dangerous) the benefits of using FMDB are even more compelling.

Sqlite database cannot read column

I have a DBManager wich is fetching data from database (sqlite file). All other queries are fine, but this one seems to be somehow not working
-(NSArray *)readCountries{
NSLog(#"[DBManager] readCountries");
NSMutableArray *countriesArray = [[NSMutableArray alloc] init];
//open db from users filesystem
if (sqlite3_open([dbPath UTF8String], &database) == SQLITE_OK) {
const char* sql = "SELECT DISTINCT country FROM aed ORDER BY rowid";
sqlite3_stmt *statement;
if (sqlite3_prepare_v2(database, sql, -1, &statement, NULL) == SQLITE_OK) {
//loop through results
while (sqlite3_step(statement) == SQLITE_ROW) {
//read data from record
NSString *_country;
char* tmpCountry = (char*)sqlite3_column_text(statement, 1);
NSLog(#"tmpCountry = %#", [NSString stringWithUTF8String:tmpCountry]);
if (tmpCountry != NULL) {
_country = [NSString stringWithUTF8String:tmpCountry];
}else{
_country = #"n/a";
}
NSLog(#"country = %#", _country);
[countriesArray addObject:_country];
}
}
//finalize statement
sqlite3_finalize(statement);
}
//close database
sqlite3_close(database);
NSLog(#"[DBManager] countriesArray has %d objects", [countriesArray count]);
return (NSArray*)countriesArray;
}
All I get from logs, that my array has 5 objects, which is fine - but it souldn't be only "n/a"... any idea? Other queries are good, they mostly use sqlite3_column_text so I don't get it, why it's not working here - maybe a fresh eye will help.
This is a confusing inconsistency with the sqlite C-api. When using the sqlite3_column_xxx functions, the column index is 0-based. But with the sqlite3_bind_xxx functions, the column index is 1-based.
Change this:
char* tmpCountry = (char*)sqlite3_column_text(statement, 1);
to:
char* tmpCountry = (char*)sqlite3_column_text(statement, 0);
BTW - you should add else statements to your sqlite3_open and sqlite3_prepare calls. If they fail you can log the error using the sqlite3_errmsg function.

cannot insert value to sqlite DB iOS

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);
}
}
}
}

Resources