I've completely given up on this, so if a moderator happens to come by, deleting would be great.
It doesn't hurt to leave this question up, but CoreData is so much nicer, you know?
I have a sqlite database for handling the contents of a table. It's great and everything (much easier than other options I looked at), but I'm having trouble with ints. The first time I go to edit an item after launching the app, the field for the int is empty. Re-entering works fine, it saves and appears in the table, but the next edit (without reopening the app) sets the second item's int to that of the first.
i.e., A(1) resets to A(0). I fix it (A(1)), but then B(2) becomes B(1) as soon as I load the edit view. Fix it (B(2)) or not (B(1)), C(3) will then have the same (#) as B.
I still can't figure out what's causing it. Changing the int to a string (edit database column and every relevant file in the app) would certainly work, but that's a whole lot of unnecessary work just to make it slower and easier to break.
edit:
CREATE TABLE "items" ("id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, "name" VARCHAR, "need" INTEGER DEFAULT 0, "notes" TEXT)
- (void)updateItemAtIndexPath:(NSIndexPath *)path {
Item *i = (Item *)[items objectAtIndex:path.row];
int ret;
const char *sql = "update items set name = ?, need = ?, notes = ? where id = ?;";
if (!updStmt) { // build update statement
if ((ret = sqlite3_prepare_v2(database, sql, -1, &updStmt, NULL)) != SQLITE_OK) {
NSAssert1(0, #"Error building statement to update items [%s]", sqlite3_errmsg(database));
}
}
// bind values to statement
NSString *s = i.name;
if (s == NULL) s = #"";
sqlite3_bind_text(updStmt, 1, [s UTF8String], -1, SQLITE_TRANSIENT);
NSInteger n = i.need;
sqlite3_bind_int(updStmt, 2, n);
s = i.notes;
if (s == NULL) s = #"";
sqlite3_bind_text(updStmt, 3, [s UTF8String], -1, SQLITE_TRANSIENT);
n = i.itemid;
sqlite3_bind_int(updStmt, 4, n);
// now execute sql statement
if (sqlite3_step(updStmt) != SQLITE_DONE) {
NSAssert1(0, #"Error updating values [%s]", sqlite3_errmsg(database));
}
// now reset bound statement to original state
sqlite3_reset(updStmt);
}
- (void)insertItem:(Item *)item {
int ret;
const char *sql = "insert into items (name, need, notes) values (?, ?, ?);";
if (!insStmt) { // first insert - build statement
if ((ret = sqlite3_prepare_v2(database, sql, -1, &insStmt, NULL)) != SQLITE_OK) {
NSAssert1(0, #"Error building statement to insert item [%s]", sqlite3_errmsg(database));
}
}
// bind values
NSString *s = item.name;
if (s == NULL) s = #"";
sqlite3_bind_text(insStmt, 1, [s UTF8String], -1, SQLITE_TRANSIENT);
NSInteger n = item.need;
sqlite3_bind_int(insStmt, 2, n);
s = item.notes;
if (s == NULL) s = #"";
sqlite3_bind_text(insStmt, 3, [s UTF8String], -1, SQLITE_TRANSIENT);
// execute sql statement
if (sqlite3_step(insStmt) != SQLITE_DONE) {
NSAssert1(0, #"Error inserting item [%s]", sqlite3_errmsg(database));
}
// reset bound statement to original state
sqlite3_reset(insStmt);
[self readItems]; // refresh array
}
Instead of using sqlite3_bind_text and sqlite3_bind_int, I would try to construct the query string from the various values and use sqlite3_exec to run it. Let's call that a tryout towards a solution.
Example (warning, untested!!):
- (void)updateItemAtIndexPath:(NSIndexPath *)path {
Item *i = (Item *)[items objectAtIndex:path.row];
// validate values
NSString *name = i.name;
if (name == NULL) name = #"";
[name stringByReplacingOccurrencesOfString:#"'"
withString:#"''"];
NSInteger need = i.need;
NSString *notes = i.notes;
if (notes == NULL) notes = #"";
[notes stringByReplacingOccurrencesOfString:#"'"
withString:#"''"];
NSInteger itemid = i.itemid;
NSString *sql = [NSString stringWithFormat:
#"update items set name = '%#', need = %#, notes = '%#' where id = %#;",
name, need, notes, itemid];
// now execute sql statement
if (sqlite3_exec(database, [sql UTF8String], NULL, NULL, NULL) != SQLITE_DONE) {
NSAssert1(0, #"Error updating values [%s]", sqlite3_errmsg(database));
}
}
Related
I have a problem with sqlite, when i select a single row from table and then check sqlite3_step(statement) == SQLITE_ROW both values are different and not getting inside while statement.
This is the code:
if (sqlite3_prepare_v2(db, query_stmt, -1, &statement, NULL) == SQLITE_OK)
{
//NSLog(#"working777.............%d",sqlite3_step(statement));
while (sqlite3_step(statement) == SQLITE_ROW)
{
NSLog(#"working888.............%d",SQLITE_ROW);
NSString *addressField = [[NSString alloc] initWithUTF8String: (const char *) sqlite3_column_text(statement, 0)];
NSString *phoneField = [[NSString alloc] initWithUTF8String:(const char *)sqlite3_column_text(statement, 1)];
NSLog(#"............statement...........addressField %#, phoneField %#",addressField,phoneField);
}
sqlite3_finalize(statement);
}
sqlite3_close(db);
}
The proper way to create such a query would be like this:
NSString *querySQL = #"SELECT * FROM Major_Events WHERE temple_id = ?";
Then prepare the statement. I assume query_stmt is the char * value from querySQL.
Once the statement is prepared you then need to bind the value.
sqlite3_bind_int(statement, 1, temp_id); // bind is 1-based
Of course temp_id needs to be an int value and not a string. There are various sqlite3_bind_xxx statements for different data types. Use the appropriate one.
Once all of the query parameters are bound, you can execute the query using sqlite3_step.
The nice thing about this approach over string formats is that strings get properly escape and put in quotes for you. It's much harder to mess up and it makes your queries much safer against SQL injection attacks.
For many records:-
if (sqlite3_open([[self getDBPath] UTF8String], &database) == SQLITE_OK) {
const char *sql = "select * from Place";
sqlite3_stmt *selectstmt;
if(sqlite3_prepare_v2(database, sql, -1, &selectstmt, NULL) == SQLITE_OK) {
while(sqlite3_step(selectstmt) == SQLITE_ROW) {
}
sqlite3_finalize(selectstmt);
sqlite3_close(database);
}
}
else
{
sqlite3_close(database);
}
If you want a single record then change while to if
if(sqlite3_step(selectstmt) == SQLITE_ROW) {
rest everything will be same
I hope it helps and if your while loop is not getting executed then it means there is some problem with your query.You need to check that also.
I'm working with SQlite for the first time....
I look up a discount in the DB, and every things works fine, until i select "nothing". This happens if the amount (adNumbers) is higher or lower than specified in the DB.
Then when trying to retrieve discount value from the DB column i get an error and application crashes. I have tried to make a NULL check, but that doesn't seems to help/work.
I have tried to use
while( sqlite3_step(compiledStatement) == SQLITE_ROW){
but the i don't get anything returned at all...
Please point me in the right direction - how do i check if the DB returns any records (adNumbers are between values en the DB )
This is my method..
-(NSString *) adDisq:(NSString *)strDISQ:(NSInteger)adNumbers{
NSString *strDiscount;
strDiscount = #"00";
if(adSTMT == nil) {
const char *sql = "SELECT ID, DISCOUNT_TYPE, DESCRIPTION, AD_FROM, AD_TO, AD_DISQ FROM DISCOUNT "
"WHERE (((DISCOUNT_TYPE)=?) AND ((?) Between AD_FROM And AD_TO))";
if(sqlite3_prepare_v2(database, sql, -1, &adSTMT, NULL) != SQLITE_OK)
NSAssert1(0, #"Error while creating detail view statement. '%s'", sqlite3_errmsg(database));
}
sqlite3_bind_text(adSTMT, 1, [strDISQ UTF8String], -1, SQLITE_STATIC);
sqlite3_bind_int(adSTMT, 2, adNumbers);
if(SQLITE_DONE != sqlite3_step(adSTMT)) {
NSLog(#"SELECT went OK, getting rows");
const char *columnText = (const char *)sqlite3_column_text(adSTMT, 5);
if(columnText != NULL){
strDiscount = [NSString stringWithUTF8String:(char *)sqlite3_column_text(adSTMT, 5)];
NSLog(#"Discount: %#", strDiscount);
}
else {
strDiscount = #"00";
}
}
else{
NSAssert1(0, #"Error while getting the discount'%s'", sqlite3_errmsg(database));
}
//Reset the detail statement.
sqlite3_reset(adSTMT);
return strDiscount;
}
Problem solved
NSAssert1(0, #"Error while getting the discount'%s'", sqlite3_errmsg(database));
Was making the crash - as expected - doh !
I want to update the quantity if the menuid is already available otherwise add a new row.
I used the following code.But no row is added or updated.
sqlite3 *database;
sqlite3_stmt *addStmt=nil;
if (selection== nil) {
selection =#"Medium";
}
if (sqlite3_open([dbPath UTF8String], &database) == SQLITE_OK) {
const char *select="select quantity from item where menuid = ?";
sqlite3_stmt *selectstmt;
if(sqlite3_prepare_v2(database, select, -1, &selectstmt, NULL) == SQLITE_OK) {
while(sqlite3_step(selectstmt) == SQLITE_ROW) {
menuID= [NSString stringWithUTF8String:(char *)sqlite3_column_text(selectstmt, 0)];
char *quant = (char *)sqlite3_column_text(selectstmt,1);
quantity=[NSString stringWithUTF8String:(char *)quant];
// [self.ids addObject:menuID];
}
sqlite3_reset(selectstmt);
}
NSString *quant=[NSString stringWithFormat:#"%#",quantity];
if (quant == #"") {
if (addStmt == nil) {
// const char *sql = "delete from item";
const char *sql = "insert into item(menuid,itemName,price,quantity,spiciness) Values( ?, ?, ?, ?,?)";
if(sqlite3_prepare_v2(database, sql, -1, &addStmt, NULL) != SQLITE_OK)
NSAssert1(0, #"Error while creating add statement. '%s'", sqlite3_errmsg(database));
}
// NSLog(#"ADDSTMT:%#",addStmt);
sqlite3_bind_int(addStmt, 1, [itemId integerValue]);
sqlite3_bind_text(addStmt, 2, [name UTF8String], -1, SQLITE_TRANSIENT);
sqlite3_bind_double(addStmt, 3, [priceItem doubleValue] );
sqlite3_bind_int(addStmt, 4, number);
sqlite3_bind_text(addStmt, 5, [selection UTF8String],-1,SQLITE_TRANSIENT);
NSLog(#"Name:%#",name);
NSLog(#"MENU IDe%#",priceItem);
if(SQLITE_DONE != sqlite3_step(addStmt)){
// NSAssert1(0, #"Error while inserting data. '%s'", sqlite3_errmsg(database));
}
else
//SQLite provides a method to get the last primary key inserted by using sqlite3_last_insert_rowid
menuID = [NSDecimalNumber numberWithLongLong:sqlite3_last_insert_rowid(database)];
//Reset the add statement.
sqlite3_reset(addStmt);
}
else{
if (addStmt == nil) {
// const char *sql = "delete from item";
const char *sql = "update item set quantity= ? where menuid = ?";
if(sqlite3_prepare_v2(database, sql, -1, &addStmt, NULL) != SQLITE_OK)
NSAssert1(0, #"Error while creating add statement. '%s'", sqlite3_errmsg(database));
}
// NSLog(#"ADDSTMT:%#",addStmt);
sqlite3_bind_int(addStmt, 2, [itemId integerValue]);
number=number+[quant intValue];
sqlite3_bind_int(addStmt, 1, number);
NSLog(#"Name:%#",name);
NSLog(#"MENU IDe%#",priceItem);
if(SQLITE_DONE != sqlite3_step(addStmt)){
// NSAssert1(0, #"Error while inserting data. '%s'", sqlite3_errmsg(database));
}
else
//SQLite provides a method to get the last primary key inserted by using sqlite3_last_insert_rowid
menuID = [NSDecimalNumber numberWithLongLong:sqlite3_last_insert_rowid(database)];
//Reset the add statement.
sqlite3_reset(addStmt);
sqlite3_close(database);
}
}
I might be just lacking proper understanding of your code but it doesn't look like you're beginning and then committing a transaction in there. I might be way off base though as I've never inserted a row without using a transaction.
I found it my self:
Changed select statement to:
NSString *sqlStmt=[NSString stringWithFormat:#"select quantity from item where menuid = %# and spiciness = '%#'",itemId,selection];
Also changed the if Condition of insert statement to
if ([quanty isEqualToString:#"(null)"])
I am using the below function in my app,and i have started using the sq-lite recently and i would like to get your opinion that i am going with that correctly or not.
Since i am facing db locked issue in my app when searched i found that i need to use sqlite3 finalise statement.
what i am not sure is do i need to place one finalise statement for each sqlite3 prepare statement
Please let me know
- ( BOOL ) addNewCate:(NSString*)dbPath:(NSString*)title:(NSString*)tierOneID:(NSString*)tierTwoID{
BOOL returnVal = NO;
if (sqlite3_open([dbPath UTF8String], &database) == SQLITE_OK)
{
const char *sql = "insert into storyboard_phrases(phrase) Values(?)";
sqlite3_stmt *addStmt;
if(sqlite3_prepare_v2(database, sql, -1, &addStmt, NULL) == SQLITE_OK){
sqlite3_bind_text(addStmt, 1, [title UTF8String], -1, SQLITE_TRANSIENT);
}
if(sqlite3_step(addStmt) != SQLITE_DONE ) {
NSLog( #"Error: %s", sqlite3_errmsg(database) );
} else {
NSLog( #"Insert into row id = %d", sqlite3_last_insert_rowid(database));
int ph_id = sqlite3_last_insert_rowid(database);
int sub_category_id = [tierTwoID intValue];
int main_category_id = [tierOneID intValue];
addStmt = nil;
sql = "insert into phrase_reference(phrase_id, sub_category_id,main_category_id) Values(?,?,?)";
if(sqlite3_prepare_v2(database, sql, -1, &addStmt, NULL) == SQLITE_OK){
sqlite3_bind_int(addStmt, 1, ph_id);
sqlite3_bind_int(addStmt, 2, sub_category_id);
sqlite3_bind_int(addStmt, 3, main_category_id);
}
if(sqlite3_step(addStmt) != SQLITE_DONE ) {
NSLog( #"Error: %s", sqlite3_errmsg(database) );
} else {
NSLog( #"Insert into row id = %d", sqlite3_last_insert_rowid(database));
returnVal = YES;
}
}
sqlite3_finalize(addStmt);
}
sqlite3_close(database);
return returnVal;
}
hii you get the locked issues in log right, that means your database is open and you doing some changes in that database so close database and try again to run application and insert in table...
hope this will help you..
hii every one
i am using following method to insert data into data base , but it will save the first entered value only all the time
the following method is in the insertUpdateDelete class
- (void) InsertRecord {
if(addStmt == nil) {
NSString *nsql = [NSString stringWithFormat:#"insert into tbl_Users(FirstName,MiddleName) Values('%#','%#')",strFirstName,strMiddleName];
const char *sql = [nsql UTF8String];
if(sqlite3_prepare_v2(database, sql, -1, &addStmt, NULL) != SQLITE_OK)
{
NSAssert1(0, #"Error while creating add statement. '%s'", sqlite3_errmsg(database));
}
}
if(SQLITE_DONE != sqlite3_step(addStmt))
NSAssert1(0, #"Error while inserting data. '%s'", sqlite3_errmsg(database));
else
//SQLite provides a method to get the last primary key inserted by using sqlite3_last_insert_rowid
intID = sqlite3_last_insert_rowid(database);
//Reset the add statement.
sqlite3_reset(addStmt);
}
through following code i am calling this method, tfText[0] & tfText[1] are text field variable , problem is,, on every click of save after entering some data in text field, it will save only the first entered value into the data base
- (void) save_Clicked
{
iICS_testAppDelegate *appDelegate = (iICS_testAppDelegate *)[[UIApplication sharedApplication] delegate];
//Create a Items Object.
insertUpdateDelete *objInsertUpdateDelete = [[insertUpdateDelete alloc] init];
objInsertUpdateDelete.strFirstName = tfText[0].text;
objInsertUpdateDelete.strMiddleName = tfText[1].text;
[appDelegate InsertRecord:objInsertUpdateDelete];
}
can any one help me,,,,thanx in advance
const char *addRecord = "insert into Test(taskname, desc) values(?, ?)";
sqlite3_stmt *statement;
if(sqlite3_prepare_v2(database, addRecord, -1, &statement, NULL) != SQLITE_OK)
{
NSLog(#"Error while Inserting Record :- '%s'", sqlite3_errmsg(database));
sqlite3_finalize(statement);
return -1;
}
sqlite3_bind_text(statement, 1, [Ttitle UTF8String], -1, SQLITE_TRANSIENT);
sqlite3_bind_text(statement, 3, [Tdesc UTF8String], -1, SQLITE_TRANSIENT);
if(SQLITE_DONE != sqlite3_step(statement))
{
NSLog(#"Error1 while Inserting Record :- '%s'", sqlite3_errmsg(database));
sqlite3_finalize(statement);
return -1;
}
else
{
NSLog(#"Record Inserted Successfully.");
sqlite3_finalize(statement);
return sqlite3_last_insert_rowid(database);
}