I have a problem that is haunting me a few days. All I want to do is add a command inside the method 'ViewDidLoad' which will make entering data into sqlite, which would make it simple do not need other fields and buttons, so, on the simulation runs, the new record will be inserted automatically in sqlite, so I try this:
In SQLite Manager Database (Plugin in firefox), I create a New Database who name is 'registros', and the program save it 'registros.sqlite'
I create this table:
CREATE TABLE "main"."campos" ("id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL UNIQUE , "campo1" VARCHAR, "campo2" VARCHAR, "campo3" VARCHAR)
In my project file, all I did was, create a file who name is 'MYFristViewController' with xib file, In the 'build Phases' I add the 'libsqlite3.dylib'. In the MyFristViewController.m I add this code:
#import "MyFristViewController.h"
#import <sqlite3.h>
#implementation MyFristViewController
- (void)viewDidLoad{
[super viewDidLoad];
sqlite3 *db;
NSString *dbPath = [[[NSBundle mainBundle] resourcePath ]stringByAppendingPathComponent:#"registros.sqlite"];
sqlite3_open([dbPath UTF8String], &db);
char *sql = "INSERT INTO campos (campo1,campo2,campo3) VALUES (?,?,?)";
sqlite3_stmt *stmt;
int resultado2 = sqlite3_prepare_v2(db, sql, -1, &stmt, nil);
sqlite3_bind_text(stmt, 1, [#"Campo_01" UTF8String], -1, SQLITE_TRANSIENT);
sqlite3_bind_text(stmt, 2, [#"Campo_02" UTF8String], -1, SQLITE_TRANSIENT);
sqlite3_bind_text(stmt, 3, [#"Campo_03" UTF8String], -1, SQLITE_TRANSIENT);
resultado2 = sqlite3_step(stmt);
sqlite3_finalize(stmt);
}
#end
As a beginner I'm not sure what else to do, I even tried modifying the fifth parameter of the command 'sqlite3_bind_text' to SQLITE_STATIC or SQLITE_TRANSIENT, but it seems that the values were not added to the database, could someone help me?
to create a new register in database, in .h file (Inherited NSObject), do you need import sqlite3.h, get the path of database:
#interface RegistroCrud : NSObject{
sqlite3 *bd;
}
-(NSString *) getPathBD;
-(void)newRegister:(NSString *)campo1 campo2:(NSString *)campo2 campo3:(NSString *)campo3;
getPathDB method is to get the database if does exits, or create it if does not exits
in .m file:
-(NSString *)getPathBD
{
NSString *dirDocs;
NSArray *rutas;
NSString *rutaBD;
rutas = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
dirDocs = [rutas objectAtIndex:0];
NSFileManager *fileMgr = [NSFileManager defaultManager];
rutaBD = [[NSString alloc] initWithString:[dirDocs
stringByAppendingPathComponent:#"registros.sqlite"]];
if([fileMgr fileExistsAtPath:rutaBD] == NO){
[fileMgr copyItemAtPath:[[[NSBundle mainBundle]resourcePath]stringByAppendingPathComponent:#"registros.sqlite"] toPath:rutaBD error:NULL
];
}
return rutaBD;
}
-(void)newRegister:(NSString *)campo1 campo2:(NSString *)campo2 campo3:(NSString *)campo3
{
NSString *pathDB = [self getPathBD];
if(!(sqlite3_open([pathDB UTF8String], &bd) == SQLITE_OK)){
NSLog(#"No se puede conectar con la BD");
return;
} else {
NSString *sqlInsert = [NSString stringWithFormat:#"INSERT OR IGNORE INTO campos (campo1,campo2,campo3) VALUES (%#,%#,'%#')",campo1,campo2,campo3];
const char *sql = [sqlInsert UTF8String];
sqlite3_stmt *sqlStatement;
if(sqlite3_prepare_v2(bd, sql, -1, &sqlStatement, NULL) != SQLITE_OK){
NSLog(#"Problema al preparar el statement");
return;
} else {
if(sqlite3_step(sqlStatement) == SQLITE_DONE){
sqlite3_finalize(sqlStatement);
sqlite3_close(bd);
}
}
}
}
Do you need have the registros.sqlite in the project
there is a tutorial in spanish: http://www.imaginaformacion.com/tutoriales/crear-una-aplicacion-con-sql-lite-en-ios-5-parte-i/ to make crud in database in ios with sqlite, ;)
I tried many things but did not get any results, here I leave with you the files of my project:
www.fazerbem.com.br/TesteUltimoSql.zip
Related
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);
}
I'm creating an app for my school project that has to write data to my sqlite database. It works, as long as the app is running active but as soon as the app closes, my added data is gone and when I want to read this data this will not work off course. I included both my loadData and saveData methods. The two database paths are the same in both functions so it's not that I'm writing my data elsewhere. I really can't find the solution or the problem. I even get the insert success in my output, so the insert is successful.
- (void) saveData:(id)sender{
NSString *sqldb = [[NSBundle mainBundle] pathForResource:#"PXLate" ofType:#"sqlite3"];
sqlite3_stmt *stmt;
NSString *queryInsert = #"INSERT INTO assignments (name, lesson, dueDate, notification, start, at) VALUES ('abc','abc', 'abc', 1, 'abc', 'abc')";
NSLog(#"%#",sqldb);
NSLog(#"%#",queryInsert);
if(sqlite3_open([sqldb UTF8String], &_PXLate) == SQLITE_OK)
{
sqlite3_prepare_v2(_PXLate, [queryInsert UTF8String], -1, &stmt, NULL);
if(sqlite3_step(stmt)==SQLITE_DONE)
{
NSLog(#"insert success");
}
else
{
NSLog(#"insert un success");
NSAssert1(0, #"Error: failed to prepare statement with message '%s'.", sqlite3_errmsg(_PXLate));
}
int success=sqlite3_step(stmt);
if (success == SQLITE_ERROR)
{
NSAssert1(0, #"Error: failed to insert into the database with message '%s'.", sqlite3_errmsg(_PXLate));
//[_PXLate save:&error];
} sqlite3_finalize(stmt);
}
sqlite3_close(_PXLate);
}
and my loadData function
- (void) loadData:(id)sender
{
//path for database
NSString *sqldb = [[NSBundle mainBundle] pathForResource:#"PXLate" ofType:#"sqlite3"];
//check if present
NSFileManager*fm=[NSFileManager defaultManager];
NSLog(#"path: %#", sqldb);
const char *dbpath = [sqldb UTF8String];
sqlite3_stmt *statement;
if (sqlite3_open(dbpath, &_PXLate) == SQLITE_OK)
{
NSString *querySQL = [NSString stringWithFormat: #"SELECT * FROM assignments WHERE name='abc'", _label.text];
const char *query_stmt = [querySQL UTF8String];
NSLog(#"name");
NSLog(querySQL);
int response = sqlite3_prepare_v2(_PXLate, query_stmt, -1, &statement, NULL);
NSLog(#"response %d", response);
if (response == SQLITE_OK)
{
NSLog(#"name");
if (sqlite3_step(statement) == SQLITE_ROW)
{
NSString *namefield = [[NSString alloc]
initWithUTF8String:
(const char *) sqlite3_column_text(
statement, 0)];
NSLog(#"name:%#", namefield);
_label.text = namefield;
} else {
_label.text = #"Match not found";
}
sqlite3_finalize(statement);
}
sqlite3_close(_PXLate);
}
}
You have to copy your sqlite to the documents directory and then work with that. Example:
self.databaseName = #"databasename.sqlite";
// Get the path to the documents directory and append the databaseName
NSArray *documentPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDir = [documentPaths objectAtIndex:0];
self.databasePath = [[NSString alloc]init];
self.databasePath = [documentsDir stringByAppendingPathComponent:self.databaseName];
[self checkAndCreateDatabase];
And the create method:
-(void)checkAndCreateDatabase
{
NSFileManager *fileManager = [NSFileManager defaultManager];
NSString *databasePathFromApp = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:self.databaseName];
[fileManager copyItemAtPath:databasePathFromApp toPath:self.databasePath error:nil];
}
A couple of observations:
As Retterdesdialogs said, you should
Check for existence of database in Documents;
If not there, copy from bundle to Documents; and
Open database from Documents.
You should not open database from bundle, because on the device that folder is read-only.
In your INSERT statement you are not checking the response of sqlite3_prepare_v2, which is a very common source of errors. If this is not SQLITE_OK, you should immediately log sqlite3_errmsg, before you call sqlite3_step.
You are performing sqlite3_step twice in the INSERT statement.
In loadData, you are not logging sqlite3_errmsg if sqlite3_prepare_v2 failed. Always look at sqlite3_errmsg upon any error.
im Working on inserting IMAGE in to Database using sqlite in Xcode 4.6 ,i just wanted to insert a textfield and uiimageview(having dynamically generated barcode image).
unfortunately im getting " Error is: out of memory "
hear is the code I'm using ,plz let me know where my mistake is & Let me know for more details
* 1. Database creation*
-(void)createoropendb {
NSArray *path =NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *docpath =[path objectAtIndex:0];
dbpathstring =[docpath stringByAppendingPathComponent:#"DataBase.db"];
char *error;
NSFileManager *filemanager =[NSFileManager defaultManager];
if (![filemanager fileExistsAtPath:dbpathstring])
{
const char *dbpath =[dbpathstring UTF8String];
if (sqlite3_open(dbpath, &barcodeDB) == SQLITE_OK)
{
const char *sql_start ="CREATE TABLE IF NOT EXISTS DBTABLE1(NAME TEXT UNIQUE,IMAGEURL BLOB)";
NSLog(#"db created");
sqlite3_exec(barcodeDB, sql_start,NULL,NULL, &error);
sqlite3_close(barcodeDB);
}
}
}
* 2.button to insert data*
- (IBAction)savedata:(id)sender {
UIImage *image =imageView.image;
NSData *imageData=UIImagePNGRepresentation(image);
[self SaveImagesToSql: imageData.bytes:Uimagetext.text];
}
* 3.method to insert data*
- (void) SaveImagesToSql: (NSData*) imgData :(NSString*) mainUrl {
const char* sqliteQuery = "INSERT INTO DBTABLE1(NAME,IMAGEURL) VALUES (?, ?)";
sqlite3_stmt* statement;
if( sqlite3_prepare_v2(barcodeDB, sqliteQuery, -1, &statement, NULL) == SQLITE_OK )
{
sqlite3_bind_text(statement, 1,[mainUrl UTF8String], -1, SQLITE_TRANSIENT);
sqlite3_bind_blob(statement, 2,[imgData bytes],[imgData length], SQLITE_TRANSIENT);
sqlite3_step(statement);
NSLog( #"Saved image successfully" );
}
else
{
NSLog( #"SaveBody: Failed from sqlite3_prepare_v2. Error is: %s",sqlite3_errmsg(barcodeDB) );
}
// Finalize and close database.
sqlite3_finalize(statement);
}
The return code (which is not SQLITE_OK) is undoubtedly returning SQLITE_MISUSE, meaning that you're trying to use a database that you haven't opened yet. Your createoropendb is creating and opening if the database doesn't exist, but if it does exist, you're not opening it (and even if it did exist, you're closing it after creating it).
Bottom line, if the database is not opened when you call sqlite3_prepare, that function will return SQLITE_MISUSE, any calls to sqlite3_errmsg will return a misleading "Out of memory" text message.
i have a view Controller called as VegQuantity which does totalcost=(quantity*cost of the dish) and inserts the itemname,quantity,totalcost into a table called as FINALORDER with database name FinalOrder
sqlite3_stmt *statement;
const char *dbpath = [databasePath UTF8String];
if (sqlite3_open(dbpath, &FinalOrder) == SQLITE_OK)
{
NSString *insertSQL = [NSString stringWithFormat: #"INSERT INTO FINALORDER (itemname, quantity, totalcost) VALUES (\"%#\", \"%#\", \"%#\")", itemName.text, input.text, output.text];
const char *insert_stmt = [insertSQL UTF8String];
sqlite3_prepare_v2(FinalOrder, insert_stmt, -1, &statement, NULL);
if (sqlite3_step(statement) == SQLITE_DONE)
{
// status.text = #"Contact added";
// name.text = #"";
// address.text = #"";
// phone.text = #"";
NSLog(#"added");
} else {
NSLog(#"Couldnt add");
}
sqlite3_finalize(statement);
sqlite3_close(FinalOrder);
}
Final View Controller viewdidload method
const char *dbpath = [databasePath UTF8String];
sqlite3_stmt *statement;
if (sqlite3_open(dbpath, &FinalOrder) == SQLITE_OK)
{
NSString *querySQL = [NSString stringWithFormat: #"SELECT * FROM FINALORDER"];
const char *query_stmt = [querySQL UTF8String];
if (sqlite3_prepare_v2(FinalOrder, query_stmt, -1, &statement, NULL) == SQLITE_OK)
{
if (sqlite3_step(statement) == SQLITE_ROW)
{
NSString *itemname = [[NSString alloc] initWithUTF8String:(const char *) sqlite3_column_text(statement, 0)];
item.text = itemname;
NSString *qua = [[NSString alloc] initWithUTF8String:(const char *) sqlite3_column_text(statement, 1)];
quantity.text = qua;
NSString *total = [[NSString alloc] initWithUTF8String:(const char *) sqlite3_column_text(statement, 2)];
totalcost.text=total;
}
sqlite3_finalize(statement);
}
sqlite3_close(FinalOrder);
}
But i keep getting this error called expected expression before FinalOrder,and is it correct for me to write this code inside viewdidload? i dont have any button in Final view controller i have a button called order in a view controller called as Restaurant which actually shows me Final view controller..am i supposed to search for the db file again in the Final viewcontroller and i am sorry question seems kind of vague but in brief i just want to know how to retrieve and display the data which i have inserted in VegQuantity view controller into the final view controller thanks
I believe that the problem must rest in the definition of FinalOrder which, on the basis of the error message, looks like has been defined as a class, not as a sqlite3 * variable. Given that the scope of your usage of the database is limited to these two methods, I'd suggest defining a sqlite3 * within that scope, and use that, such as:
- (void)saveRecord
{
sqlite3 *database;
sqlite3_stmt *statement;
const char *dbpath = [databasePath UTF8String];
if (sqlite3_open(dbpath, &database) == SQLITE_OK)
{
[self purgeTable:database];
NSString *insertSQL = #"INSERT INTO FINALORDER (itemname, quantity, totalcost) VALUES (?, ?, ?)";
if (sqlite3_prepare_v2(database, [insertSQL UTF8String], -1, &statement, NULL) == SQLITE_OK)
{
sqlite3_bind_text(statement, 1, [itemName.text UTF8String], -1, NULL);
sqlite3_bind_int(statement, 2, [input.text intValue]);
sqlite3_bind_double(statement, 3, [output.text doubleValue]);
if (sqlite3_step(statement) == SQLITE_DONE)
{
// status.text = #"Contact added";
// name.text = #"";
// address.text = #"";
// phone.text = #"";
NSLog(#"added");
} else {
NSLog(#"%s Couldn't add; errmsg='%s'", __FUNCTION__, sqlite3_errmsg(database));
}
sqlite3_finalize(statement);
} else {
NSLog(#"%s Couldn't prepare; errmsg='%s'", __FUNCTION__, sqlite3_errmsg(database));
}
sqlite3_close(database);
}
}
Note, in addition to using a sqlite3 * variable for the database, to make this a little more robust:
I have replaced the stringWithFormat statement that built the SQL insert statement with an INSERT statement that uses the ? placeholders and then use sqlite3_bind_text to bind values to that statement. This way, if someone entered a value that included a quotation mark, the insert statement will still work (your original implementation would have crashed and/or was susceptible to a SQL injection attack).
I have also added the sqlite3_errmsg statements so if something goes wrong, I know what the problem was.
Rather than treating these three fields as text fields, I'm assuming your table is defined as CREATE TABLE IF NOT EXISTS FINALORDER (itemname TEXT, quantity INT, totalcost REAL); and therefore use text, int, and double bind statements.
This, incidentally, invokes a purgeTable method, so if you run it twice, it will remove the old record in there:
- (void)purgeTable:(sqlite3 *)database
{
if (sqlite3_exec(database, "DELETE FROM FINALORDER;", NULL, NULL, NULL) != SQLITE_OK)
NSLog(#"%s Couldn't purge table %s", __FUNCTION__, sqlite3_errmsg(database));
}
Anyway, you can then read this data via:
- (void)loadRecord
{
sqlite3 *database;
const char *dbpath = [databasePath UTF8String];
sqlite3_stmt *statement;
if (sqlite3_open(dbpath, &database) == SQLITE_OK)
{
NSString *querySQL = #"SELECT * FROM FINALORDER";
if (sqlite3_prepare_v2(database, [querySQL UTF8String], -1, &statement, NULL) == SQLITE_OK)
{
if (sqlite3_step(statement) == SQLITE_ROW)
{
NSString *itemname = [[NSString alloc] initWithUTF8String:(const char *) sqlite3_column_text(statement, 0)];
item.text = itemname;
//[itemname release]; // if not ARC, uncomment this line
int qua = sqlite3_column_int(statement, 1);
quantity.text = [NSString stringWithFormat:#"%1d", qua];
double total = sqlite3_column_double(statement, 2);
totalcost.text = [NSString stringWithFormat:#"%1.2f", total];
}
sqlite3_finalize(statement);
} else {
NSLog(#"%s Couldn't prepare; errmsg='%s'", __FUNCTION__, sqlite3_errmsg(database));
}
sqlite3_close(database);
}
}
Note,
I've added a sqlite3_errmsg log statement if the sqlite3_prepare fails, and I've retired the stringWithFormat (because you weren't formatting anything).
Given that quantity was INT and total was REAL, I'm retrieving the values using the appropriate variation of sqlite3_column_text, sqlite3_column_int, or sqlite3_column_double, as appropriate.
I infer that you're not using ARC and therefore, the [NSString alloc] must have an associated release or autorelease.
Finally, in our chat, you said that you received an error message (presumably an "Undefined Symbols" message) that said:
OBJC_CLASS_$"_FinalOrder"
This means that you are trying to use an object class of FinalOrder, but you haven't defined that class anywhere. Take a look at which .o files it's reporting this error for and look at the corresponding .m file, and look for your use of the FinalOrder class there. You clearly have a FinalOrder class interface defined somewhere, but never defined the class implementation, or, if you have one, for some reason it's not included in your target's "Compile Sources" listing, so double check it's here:
Finally, by the way, make sure your database is in the Documents folder, not trying to open a copy of the database in your project's bundle (because that's read only). If you have a copy of the database in your bundle, just check to see if you already have it in you Documents folder, and if not, copy it from the bundle to the Documents folder.
I am trying to insert text data into sqlite3 database in iOS.
I wrote following codes to save data into sqlite3 database.
NSFileManager *fileMgr = [NSFileManager defaultManager];
NSString *dbPath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:#"MgDB.sqlite"];
BOOL success = [fileMgr fileExistsAtPath:dbPath];
if(!success)
{
NSLog(#"File Not Found");
}
if((!sqlite3_open([dbPath UTF8String], &database) == SQLITE_OK))
{
NSLog(#"Error in MyInfo");
}
const char *sql = "Insert into MyDB (name,address,email) values('%#','%#','%#')";
sqlite3_bind_text(sqlStmt, 0, [Name UTF8String], -1, SQLITE_TRANSIENT);
sqlite3_bind_text(sqlStmt, 1, [Address UTF8String], -1, SQLITE_TRANSIENT);
sqlite3_bind_text(sqlStmt, 2, [Email UTF8String], -1, SQLITE_TRANSIENT);
if(sqlite3_prepare(database, sql, -1, &sqlStmt, NULL))
{
NSLog(#"Error in Loading database");
}
if (sqlite3_exec(database, sql, NULL, NULL, NULL) == SQLITE_OK)
{
return sqlite3_last_insert_rowid(database);
}
if(sqlite3_step(sqlStmt) == SQLITE_ROW)
{
NSLog(#"ERROR");
}
}
#catch (NSException *exception)
{
NSLog(#"%#",exception);
}
#finally
{
sqlite3_finalize(sqlStmt);
sqlite3_close(database);
}
according to my above code,I return the last insert ROWID to check that inserted or not.
After saved text data in View,the ROWID have increased.
However when i check my database with FireFox sqlite3 tools, there are no any data that i have inserted.
So i stop running and ReRun my app and add data again.
The last insert ROWID is the same with old count.Not increase even one.
I want to know why it's doesn't save any data into sqlite database.
Is there any problem in my code?
Please help me.
Thanks in advance.
NSString *dbPath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:#"MgDB.sqlite"];
You can't write to files included in the application bundle. Create (or copy) the database in the Documents directory instead.
See QA1662.