i have array namely _twoArray it contains data something like below
ha ha 2d array(
(
"Anand Kapadiya",
"Alok Darji",
"Akash Parikh",
"Ajay Desai",
"Aysu Can",
"Ayegba James",
"Ashish Modi",
"Arks Patel",
"Archit Patel",
"Anzey Khodorovskyy"
),
(
"12/01",
"08/13/1990",
"12/09/1989",
"05/22/1988",
"04/14/1992",
"12/15/1905",
"09/08",
"05/27/1990",
"05/22/1990",
"02/06"
)
)
i have database with one table and 2 fields one is Names and another is birth dates how can i add birth dates and names in database from this 2d array i am trying following code
for (id obj in _twoArray)
{
sqlite3_stmt *stmt;
int x;
char *update = "insert into PersonNamesAndBirthDates (Names,Birthdates) values(? ?);";
x = sqlite3_prepare_v2(database1, update, -1, &stmt, nil);
if (x == SQLITE_OK)
{
NSLog(#"PersonNamesAndBirthDates is -->%#",[NSString stringWithFormat:#"%#",obj]);
sqlite3_bind_text(stmt, 1, [[NSString stringWithFormat:#"%#",obj] UTF8String],-1, NULL);
sqlite3_bind_text(stmt, 2, NULL,-1, NULL);
}
if (sqlite3_step(stmt) != SQLITE_DONE){}
NSLog(#"Error: ");
sqlite3_finalize(stmt);
}
plz suggest me something or if this is not possible then tell me how can i add 2 different array in table at same time
Your _twoArray contains two object which are in turn NSArray. Now it is fixed that you will have always two array within one array, then try this
NSArray *nameArr = [_twoArray objectAtIndex:0];
NSArray *bdArr = [_twoArray objectAtIndex:1];
if (sqlite3_open([databaseFilePath UTF8String], &database1) == SQLITE_OK)
{
for (int i = 0; i< [nameArr count]; i++)
{
sqlite3_stmt *stmt;
int x;
char *update = "insert into PersonNamesAndBirthDates (Names,Birthdates) values(? ?);";
x = sqlite3_prepare_v2(database1, update, -1, &stmt, nil);
if (x == SQLITE_OK)
{
NSLog(#"PersonName is -->%#",[NSString stringWithFormat:#"%#",[nameArr objectAtIndex:i]]);
NSLog(#"BirthDates is -->%#",[NSString stringWithFormat:#"%#",[bdArr objectAtIndex:i]]);
sqlite3_bind_text(stmt, 1, [[NSString stringWithFormat:#"%#",[nameArr objectAtIndex:i]] UTF8String],-1, NULL);
sqlite3_bind_text(stmt, 2, [[NSString stringWithFormat:#"%#",[bdArr objectAtIndex:i]] UTF8String],-1, NULL);
}
if (sqlite3_step(stmt) != SQLITE_DONE){}
NSLog(#"Error: ");
sqlite3_finalize(stmt);
}
sqlite3_close(database1);
}
Your array contain two objects which are array type.
for (int i=0;i<[[_twoArray objectAtIndex:0] count];i++)
{
sqlite3_stmt *stmt;
int x;
char *update = "insert into PersonNamesAndBirthDates (Names,Birthdates) values(? ?);";
x = sqlite3_prepare_v2(database1, update, -1, &stmt, nil);
if (x == SQLITE_OK)
{
NSLog(#"PersonName:%# BirthDate:%#",[[NSString stringWithFormat:#"%#",[[_twoArray objectAtIndex:0] objectAtIndex:i]],[[NSString stringWithFormat:#"%#",[[_twoArray objectAtIndex:1] objectAtIndex:i]]);
sqlite3_bind_text(stmt, 1, [[NSString stringWithFormat:#"%#",[[_twoArray objectAtIndex:0] objectAtIndex:i]] UTF8String],-1, NULL);
sqlite3_bind_text(stmt, 2, NULL,-1, NULL);
}
if (sqlite3_step(stmt) != SQLITE_DONE){}
NSLog(#"Error: ");
sqlite3_finalize(stmt);
}
You can't do it in the way you are trying to, as your for loop is providing you a array at a time not the variables. You can use following two ways:
create two arrays name and dob and add records respectively on same index then use for loop for the index of any array and use 2 string variable to store data of same index and then use these to create query
Or you can create a NSDictionary in which you can store, name and dob, such as
NSMutableArray *array = [[NSMutableArray alloc] initWithCapacity:0];
while (records) {
NSDictionary *dictionary = [NSDictionary dictionaryWithObjectsAndKeys:
#"Mr. X", #"name"
#"13/12/82", #"dob"
nil];
[array addObject:dictionary];
records--;
}
And then create each query for index. to retrieve dictionary, values and to create query you use following code,
for (NSDictionary *dict in array) {
NSString *userName = [dict valueForKey:#"name"];
NSString *dateOfBirth = [dict valueForKey:#"dob"];
//write query here
}
Related
I am trying to retrieve some data from my sqlite table base on a date, but I am getting EXC_BAD_ACCESS(code=EXC_1386_GPFLT) error. Here is my method to fetch data-
-(NSMutableArray*)fetchDataFromTable:(NSString*)tableName whenDate:(NSString*)activeDate{
NSMutableArray *resultArray=[[NSMutableArray alloc]init];
NSString *query = [NSString stringWithFormat:#"select * from %# where ActiveDate = \"%#\"", tableName, activeDate];
if ([self canOpenDatabase]) { //checks if database can be openned
sqlite3_stmt *statement=nil;
if(sqlite3_prepare_v2(database, [query UTF8String], -1, &statement, NULL) == SQLITE_OK) {
while (sqlite3_step(statement) == SQLITE_ROW){
NSMutableArray *fetchedResults=[[NSMutableArray alloc]init];
int numberOfColumns = sqlite3_column_count(statement);
for (int i=0; i< numberOfColumns; i++){
char *dataAsChars = (char *)sqlite3_column_text(statement, i);
if (dataAsChars != NULL) {
NSString *dataString = [[NSString alloc] initWithUTF8String:dataAsChars];
[fetchedResults addObject:dataString];
}
}
[resultArray addObject:fetchedResults];
sqlite3_finalize(statement);
sqlite3_close(database);
}
}
else{
NSLog(#"Data can not be retrived");
}
return resultArray;
}
else{
return resultArray;
}
}
I also trying printing the query. It shows
select * from Time_table where ActiveDate = "2016-01-01"
Please Help me out.
There are several issues.
Pair the call to sqlite3_close with the success of opening the database.
Pair the call to sqlite_finalize with the success of preparing the statement.
Don't close the database or finalize the statement inside the loop.
Don't build queries using stringWithFormat. Properly bind values into the prepared statement.
The issue was very obvious yet very intuitive. I am glad that I faced this issue. At least I won't do it again. So, here is the simple fix and the reason behind it-
In case of database object fetching, EXC_BAD_ACCESS normally happens when -
An object is not initialised or
An object is already released untimely
So, in case, I were never to use the prepared statement or completely done working with the statement, I should use sqlite_finalize. In may method, I used the statement after I finalised the statement.
So the easy fix was to finalise after the while statement-
-(NSMutableArray*)fetchDataFromTable:(NSString*)tableName whenDate:(NSString*)activeDate{
NSMutableArray *resultArray=[[NSMutableArray alloc]init];
NSString *query = [NSString stringWithFormat:#"select * from %# where ActiveDate = \"%#\"", tableName, activeDate];
if ([self canOpenDatabase]) {
sqlite3_stmt *statement=nil;
if(sqlite3_prepare_v2(database, [query UTF8String], -1, &statement, NULL) == SQLITE_OK) {
while (sqlite3_step(statement) == SQLITE_ROW){
NSMutableArray *fetchedResults=[[NSMutableArray alloc]init];
int numberOfColumns = sqlite3_column_count(statement);
for (int i=0; i< numberOfColumns; i++){
char *dataAsChars = (char *)sqlite3_column_text(statement, i);
if (dataAsChars != NULL) {
NSString *dataString = [[NSString alloc] initWithUTF8String:dataAsChars];
[fetchedResults addObject:dataString];
}
}
[resultArray addObject: fetchedResults];
}
sqlite3_finalize(statement);
}
else{
NSLog(#"Data can not be retrived");
}
sqlite3_close(database);
return resultArray;
}
else{
return resultArray;
}
}
I am inserting Russian words into SQLite DB and inside the database (using some DBMS software) they are looking good. But when I retrieve them, the look like this: —É–ª. –°–∞–º–æ–≥–æ –∫—Ä—É—Ç–æ–≥–æ —á—É–≤–∞–∫–∞.
Insert code:
NSString *sql = #"INSERT INTO (. . .) "
" VALUES (. . . )";
sqlite3_stmt *insert;
int result = sqlite3_prepare_v2(self.db, [sql UTF8String], -1, &insert, NULL);
if (result == SQLITE_OK) {
sqlite3_bind_text(insert, 1, [favouriteAction.nameAction UTF8String], -1, SQLITE_TRANSIENT);
. . .
Select code:
NSString *sql = nil;
sql = [NSString stringWithFormat:#"SELECT * FROM UserFavourites"];
sqlite3_stmt *select;
int result = sqlite3_prepare_v2(self.db, [sql UTF8String], -1, &select, NULL);
NSMutableArray* userFavourites = [[NSMutableArray alloc]initWithCapacity:20];
NSLog(#"SQLITE_OK %d", result);
if (result == SQLITE_OK) {
// sqlite3_bind_int(select, 1, (int)user_id);
while (sqlite3_step(select) == SQLITE_ROW) {
NSMutableArray *values = [[NSMutableArray alloc] initWithCapacity:8];
ActionCreation* ac = [[ActionCreation alloc]init];
// get the nameAction:
[values addObject:
[NSString stringWithFormat:#"%s", sqlite3_column_text(select, 0)]];
How to fix this problem?
Thank you.
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)]];
perhaps I'm blind but I cant figure out what I am doing wrong.
after the 2 runs (there are only 2 values in the database) I get 2 different values like it should be. Then I write it into the NSMutableArray.
But there is only the 2nd value twice. Shouldnt it add to the end of the array? What do I do wrong?
- (NSMutableArray *)getItemsFromDatabaseWithName:(NSString *)databaseName fromTable:(NSString *)tableName andConstraint:(NSString *)constraint
{
NSString *absolutePath = [[NSBundle mainBundle].resourcePath stringByAppendingPathComponent:databaseName];
NSLog(#"%#", absolutePath);
//Datenbank öffnen --- "**" bedeuten "&" verwenden
sqlite3_open([absolutePath UTF8String], &_database);
//check if there is a constraint and if not take 2nd statement
if (![constraint isEqualToString:#""])
{
_statement = [NSString stringWithFormat:#"select * from %# where %#",tableName, constraint];
}
else
{
_statement = [NSString stringWithFormat:#"select * from %#",tableName];
}
const char *charStatement = [_statement cStringUsingEncoding:NSUTF8StringEncoding];
sqlite3_stmt *results;
//new array to return values
_mutableItemArray = [NSMutableArray new];
//new ItemModel
ItemModel *tmpItem = [ItemModel new];
if (sqlite3_prepare_v2(_database, charStatement, -1, &results, NULL)== SQLITE_OK)
{
while (sqlite3_step(results) == SQLITE_ROW)
{
_charItemName = (char *)sqlite3_column_text(results, 1);
[tmpItem setItemName:[NSString stringWithUTF8String:_charItemName]];
_charItemDescription = (char *)sqlite3_column_text(results, 2);
[tmpItem setItemDescription:[NSString stringWithUTF8String:_charItemDescription]];
_charItemYear = (char *)sqlite3_column_text(results, 3);
[tmpItem setItemYear:[_dateFormat dateFromString:[NSString stringWithUTF8String:_charItemYear]]];
_charItemRecommendedBy = (char *)sqlite3_column_text(results, 4);
[tmpItem setItemRecommendedBy:[NSString stringWithUTF8String:_charItemRecommendedBy]];
_charItemImage = (char *)sqlite3_column_text(results, 5);
[tmpItem setItemImage:[NSString stringWithUTF8String:_charItemImage]];
[_mutableItemArray addObject:tmpItem];
#warning here I get the 2 items correct
NSLog(#"ItemName: %#",[tmpItem getItemName]);
NSLog(#"ItemName: %#",[tmpItem getItemDescription]);
}
}
sqlite3_close(_database);
#warning here I get 2 times the same item ???
NSLog(#"ItemName: %#",[_mutableItemArray objectAtIndex:0]);
NSLog(#"ItemName: %#",[_mutableItemArray objectAtIndex:1]);
return _mutableItemArray;
}
You just create one object tmpItem.
This will be added to the array and in the next run of the while loop you're not creating a new tmpItem but modifying the old one and add it to the array.
Therefore you will end up with an Array containing two pointers to the same object tmpItem (with the latest state).
Solution: create your tmpItem within the while loop.
If you go through your code you will see inside the while loop you are setting the same object (tmpItem) again and again,that is why your array has last updated values of the same object.
Now see below code you will notice in the while loop, we are creating new object and storing it in an NSArray.
- (NSMutableArray *)getItemsFromDatabaseWithName:(NSString *)databaseName fromTable:(NSString *)tableName andConstraint:(NSString *)constraint
{
NSString *absolutePath = [[NSBundle mainBundle].resourcePath stringByAppendingPathComponent:databaseName];
NSLog(#"%#", absolutePath);
//Datenbank öffnen --- "**" bedeuten "&" verwenden
sqlite3_open([absolutePath UTF8String], &_database);
//check if there is a constraint and if not take 2nd statement
if (![constraint isEqualToString:#""])
{
_statement = [NSString stringWithFormat:#"select * from %# where %#",tableName, constraint];
}
else
{
_statement = [NSString stringWithFormat:#"select * from %#",tableName];
}
const char *charStatement = [_statement cStringUsingEncoding:NSUTF8StringEncoding];
sqlite3_stmt *results;
//new array to return values
_mutableItemArray = [NSMutableArray new];
//new ItemModel
if (sqlite3_prepare_v2(_database, charStatement, -1, &results, NULL)== SQLITE_OK)
{
while (sqlite3_step(results) == SQLITE_ROW)
{
ItemModel *tmpItem = [ItemModel new];
_charItemName = (char *)sqlite3_column_text(results, 1);
[tmpItem setItemName:[NSString stringWithUTF8String:_charItemName]];
_charItemDescription = (char *)sqlite3_column_text(results, 2);
[tmpItem setItemDescription:[NSString stringWithUTF8String:_charItemDescription]];
_charItemYear = (char *)sqlite3_column_text(results, 3);
[tmpItem setItemYear:[_dateFormat dateFromString:[NSString stringWithUTF8String:_charItemYear]]];
_charItemRecommendedBy = (char *)sqlite3_column_text(results, 4);
[tmpItem setItemRecommendedBy:[NSString stringWithUTF8String:_charItemRecommendedBy]];
_charItemImage = (char *)sqlite3_column_text(results, 5);
[tmpItem setItemImage:[NSString stringWithUTF8String:_charItemImage]];
[_mutableItemArray addObject:tmpItem];
NSLog(#"ItemName: %#",[tmpItem getItemName]);
NSLog(#"ItemName: %#",[tmpItem getItemDescription]);
}
}
sqlite3_close(_database);
NSLog(#"ItemName: %#",[_mutableItemArray objectAtIndex:0]);
NSLog(#"ItemName: %#",[_mutableItemArray objectAtIndex:1]);
return _mutableItemArray;
}
I want to write a generate function which for inserting the data to sqlite database in the ios development,the codes are here:
-(NSInteger)executeUpdateWithSql:(NSString *)sql params:(NSMutableArray *)params
{
sqlite3_stmt *stmt;
if (sqlite3_prepare_v2(_database, [sql UTF8String], -1, &stmt, NULL) == SQLITE_OK) {
for (int i = 1; i <= params.count; i++) {
id param = [params objectAtIndex:i];
sqlite3_bind_text(stmt, i, [param UTF8String], -1, SQLITE_TRANSIENT);
}
}
NSInteger result =sqlite3_step(stmt);
if (result != SQLITE_DONE){
PBLog(#"error!");
}
return result;
}
But, if there is a int param in the params, the error message is "-[__NSCFNumber UTF8String]: unrecognized selector sent to instance 0x1dd1ea60".
I want to judge the param datatype,How to do? The datatype maybe int/float/double/bealoon/string.
then you should do something like this:
id param = [params objectAtIndex:i];
if([param isKindOfClass:[NSNumber class]])
{
NSString *tmp = [param stringValue]
}
else
{
NSString *tmp = param
}
the id can be any object type and not runt time safe.