ios sqlite3_bind_text step returns null - ios

In the following code everything seems right but the notated lines always return an error code of null no matter what data I feed them. I've researched and changed all the parameters I can think of. The first sqlite3_bind_text line is successful and the next three fail every time. I can't figure it out. Help?
-(void)fillSqliteDb
{
sqlite3 *database;
if (sqlite3_open([[self sqliteFilePath] UTF8String], &database) != SQLITE_OK) {
sqlite3_close(database);
NSAssert(0, #"Failed to open database");
}
NSString *createSQL = #"CREATE TABLE IF NOT EXISTS FUNCTIONS (nouns TEXT, verbs TEXT, adverbs TEXT, adjectives TEXT);";
char *errorMsg;
if (sqlite3_exec (database, [createSQL UTF8String], NULL, NULL, &errorMsg) != SQLITE_OK) {
sqlite3_close(database);
NSAssert(0, #"Error creating table: %s", errorMsg);
}
sqlite3_stmt *stmt;
for (int i=0; i<260; i++) {
NSString * pln = self.pluralNouns[i]; // pre-filled array of 260 words
NSString * vrb = self.verb[i]; // pre-filled array of 260 words
NSString * adv = self.adverb[i]; // pre-filled array of 260 words
NSString * adj = self.adjective[i]; // pre-filled array of 260 words
char *update = "INSERT INTO FUNCTIONS (nouns, verbs, adverbs, adjectives) VALUES (?, ?, ?, ?);";
if (sqlite3_prepare_v2(database, update, -1, &stmt, nil) == SQLITE_OK) {
sqlite3_bind_text(stmt, 1, [pln UTF8String], -1, NULL);
if (sqlite3_step(stmt) != SQLITE_DONE) // Works, word ends up in database
NSLog(#"Error updating table: %s", errorMsg);
sqlite3_bind_text(stmt, 2, [vrb UTF8String], -1, NULL);
if (sqlite3_step(stmt) != SQLITE_DONE) // ALWAYS RETURNS Error: NULL
NSLog(#"Error updating table: %s", errorMsg);
sqlite3_bind_text(stmt, 3, [adv UTF8String], -1, NULL);
if (sqlite3_step(stmt) != SQLITE_DONE) // ALWAYS RETURNS Error: NULL
NSLog(#"Error updating table: %s", errorMsg);
sqlite3_bind_text(stmt, 4,[adj UTF8String], -1, NULL);
if (sqlite3_step(stmt) != SQLITE_DONE) // ALWAYS RETURNS Error: NULL
NSLog(#"Error updating table: %s", errorMsg);
}
}
}

There are several things wrong with this code.
Only call sqlite3_prepare_v2 once. Do it before the for loop.
You need to call sqlite3_bind_xxx once for each variable, all before calling sqlite3_step.
Only call sqlite2_step once per loop. Do this at the end of the loop.
After calling sqlite3_step at the end of the loop, you need to call sqlite3_reset.
After the loop you need to call sqlite3_finalize on the prepared statement.
Since you opened the database connection at the start of the method, you need to close it at the end of the method.
Your use of errorMsg for all of the logs after checking the result of each sqlite3_step call is wrong. errorMsg is only set from the call to sqlite3_exec. To get the error message of the other calls you need to use sqlite3_errmsg.
Updated code:
- (void)fillSqliteDb {
sqlite3 *database;
if (sqlite3_open([[self sqliteFilePath] UTF8String], &database) != SQLITE_OK) {
sqlite3_close(database);
NSAssert(0, #"Failed to open database");
}
NSString *createSQL = #"CREATE TABLE IF NOT EXISTS FUNCTIONS (nouns TEXT, verbs TEXT, adverbs TEXT, adjectives TEXT);";
char *errorMsg;
if (sqlite3_exec (database, [createSQL UTF8String], NULL, NULL, &errorMsg) != SQLITE_OK) {
sqlite3_close(database);
NSAssert(0, #"Error creating table: %s", errorMsg);
}
sqlite3_stmt *stmt;
char *update = "INSERT INTO FUNCTIONS (nouns, verbs, adverbs, adjectives) VALUES (?, ?, ?, ?);";
if (sqlite3_prepare_v2(database, update, -1, &stmt, nil) == SQLITE_OK) {
for (int i=0; i<260; i++) {
NSString * pln = self.pluralNouns[i]; // pre-filled array of 260 words
NSString * vrb = self.verb[i]; // pre-filled array of 260 words
NSString * adv = self.adverb[i]; // pre-filled array of 260 words
NSString * adj = self.adjective[i]; // pre-filled array of 260 words
sqlite3_bind_text(stmt, 1, [pln UTF8String], -1, NULL);
sqlite3_bind_text(stmt, 2, [vrb UTF8String], -1, NULL);
sqlite3_bind_text(stmt, 3, [adv UTF8String], -1, NULL);
sqlite3_bind_text(stmt, 4, [adj UTF8String], -1, NULL);
if (sqlite3_step(stmt) != SQLITE_DONE) // ALWAYS RETURNS Error: NULL
NSLog(#"Error updating table: %s", sqlite3_errmsg(database));
sqlite3_reset(stmt);
}
sqlite3_finalize(stmt);
}
sqlite3_close(database);
}

Related

syntax error with dynamic ALTER sqlite3_bind_text statement in obj-c

This code throws a error [logging] near "?": syntax error in "ALTER TABLE jobs ADD COLUMN ? text"
NSArray *uArray = [NSArray arrayWithObjects:#"string1", #"string2", #"etc", nil];
const char *query = "ALTER TABLE jobs ADD COLUMN ? TEXT NOT NULL";
sqlite3_stmt *compiledStatement = nil;
sqlite3_exec((sqlite3 *)(db), "BEGIN EXCLUSIVE TRANSACTION", 0, 0, 0);
if(sqlite3_prepare((sqlite3 *)(db), query, -1, &compiledStatement, NULL) == SQLITE_OK)
{
for (NSString *obj in uArray)
{
sqlite3_bind_text(compiledStatement, 1, [obj UTF8String], -1, SQLITE_STATIC);
if (sqlite3_step(compiledStatement) != SQLITE_DONE) NSLog(#"DB not updated. Error: %s",sqlite3_errmsg((sqlite3 *)(db)));
if (sqlite3_reset(compiledStatement) != SQLITE_OK) NSLog(#"SQL Error: %s",sqlite3_errmsg((sqlite3 *)(db)));
}
}
I can't see it saying anywhere that ? can't be used with ALTER
Thoughts
You can't use parameters for table or column names

Sqlite update command is not working

When i try to update a table its giving me a
error message : near "(": syntax error
Please anybody suggest me to rectify this issue.
I am updating a table when i click the save button (Bar button item) on the tool bar which is placed below.
The problem is it's always going to else statement of sqlite3_step.
I am not getting whats the exact problem for this issue and the above mentioned error.
Any suggestions would be appreciated.
Following is my update method :
if ([databaseManager didExistDatabaseInDocumentDirectory] == YES)
{
const char *dbpath = [[databaseManager getDatabasePathFromDocument] UTF8String];
sqlite3_stmt *stmt;
if (sqlite3_open(dbpath, &scanningDB) == SQLITE_OK)
{
const char *update_stmt1 = "UPDATE FILES SET (documentType,orderNumber) VALUES (?,?) WHERE ID = ?";
sqlite3_prepare_v2(scanningDB, update_stmt1, -1, &stmt, NULL);
sqlite3_bind_text(stmt, 1, [str UTF8String], -1, SQLITE_TRANSIENT);
sqlite3_bind_text(stmt, 2, [str1 UTF8String], -1, SQLITE_TRANSIENT);
sqlite3_bind_int(stmt, 3,[num intValue]);
if(sqlite3_step(stmt)==SQLITE_DONE)
{
sqlite3_reset(stmt);
NSLog(#"Record Updated Successfully");
}
else
{
NSLog(#"Could not Update Record");
NSLog(#" error message %s",sqlite3_errmsg(scanningDB));
sqlite3_finalize(stmt);
sqlite3_close(scanningDB);
return NO;
}
sqlite3_finalize(stmt);
sqlite3_close(scanningDB);
}
else
return NO;
}
else
return NO;
Please correct your query with the following.
const char *update_stmt1 = "UPDATE FILES SET documentType = ? ,orderNumber = ? WHERE ID = ?
Hope this will help you.
Your update query is wrong.
UPDATE FILES SET (documentType,orderNumber) VALUES (?,?) WHERE ID = ?
Syntax:
UPDATE table_name
SET column1 = value1, column2 = value2...., columnN = valueN
WHERE [condition];
Your query:
UPDATE FILES SET documentType =?, orderNumber =? where ID =?, documentTypeString, Yourordernumber, yourID
Sample:
- (void) update
{
if (sqlite3_open([dbPath UTF8String], &database) == SQLITE_OK)
{
if(updateStatement == nil)
{
const char *sql = "UPDATE FILES SET documentType =?, orderNumber =? where ID =?";
if(sqlite3_prepare_v2(database, sql, -1, & updateStatement, NULL) != SQLITE_OK)
NSAssert1(0, #"Error while creating update statement. '%s'", sqlite3_errmsg(database));
}
sqlite3_bind_text(documentType
, 1, [comment UTF8String], -1, SQLITE_TRANSIENT);
sqlite3_bind_text(orderNumber
, 2, [categoria UTF8String], -1, SQLITE_TRANSIENT);
sqlite3_bind_int(ID, 3, id);
if(SQLITE_DONE != sqlite3_step(updateStatement))
NSAssert1(0, #"Error while updating data. '%s'", sqlite3_errmsg(database));
else
//SQLite provides a method to get the last primary key inserted by using sqlite3_last_insert_rowid
//noteID = sqlite3_last_insert_rowid(database);
//Reset the update statement.
sqlite3_reset(updateStatement);
sqlite3_close(database);
deleteStatement = nil;
}
else
sqlite3_close(database);
}
Basic SQLite tutorial:
http://www.tutorialspoint.com/sqlite/index.htm

SQL ERROR: near "m": syntax error. In Statement: insert into table? [duplicate]

I have one question.
I'm getting information from JSON and he returns me invalid character.
JSON give me this: "27/"" when I need this: 27". I understand this is a encode for special characters but when I use the value on NSString to make an Insert in a SQLite table, I can't use 27/" cause the insert format is this: INSERT INTO FORMATOS (ID, NOMBRE) VALUES ("17", "27"").
What method I need to Insert information correctly in the SQLlite?
for (int i = 0; i<idFormato.count; i++) {
NSString *idStr = [idFormato objectAtIndex:i];
NSString *nameStr = [nameFormato objectAtIndex:i];
insertSQL = [NSString stringWithFormat:#"INSERT INTO FORMATOS (ID, NOMBRE) VALUES (\"%#\", \"%#\")", idStr, nameStr];
//Char constant with the query encoded un UTF
const char *insert_stmt = [insertSQL UTF8String];
//Execute query
sqlite3_prepare_v2(dieneDB, insert_stmt, -1, &statement, NULL);
//Check if Statment is dne correctly
if(sqlite3_step(statement) == SQLITE_DONE){
NSLog(#"Guardado Formatos correctamente");
}
The JSON:
[
{"ID_FORMATO_INT":"17","NOMBRE_FORMATO_STR":"2,5\"","ID_USUARIO_ALTA_INT":"3","FECHA_ALTA_FORMATO_DAT":"2014-09-18 07:17:55","ID_USUARIO_MOD_INT":null,"FECHA_MOD_FORMATO_DAT":null},{"ID_FORMATO_INT":"18","NOMBRE_FORMATO_STR":"4\"","ID_USUARIO_ALTA_INT":"3","FECHA_ALTA_FORMATO_DAT":"2014-09-18 07:18:20","ID_USUARIO_MOD_INT":null,"FECHA_MOD_FORMATO_DAT":null},{"ID_FORMATO_INT":"19","NOMBRE_FORMATO_STR":"4,7\"","ID_USUARIO_ALTA_INT":"3","FECHA_ALTA_FORMATO_DAT":"2014-09-18 07:20:07","ID_USUARIO_MOD_INT":null,"FECHA_MOD_FORMATO_DAT":null},{"ID_FORMATO_INT":"20","NOMBRE_FORMATO_STR":"5,5\"","ID_USUARIO_ALTA_INT":"3","FECHA_ALTA_FORMATO_DAT":"2014-09-18 07:20:15","ID_USUARIO_MOD_INT":null,"FECHA_MOD_FORMATO_DAT":null},{"ID_FORMATO_INT":"21","NOMBRE_FORMATO_STR":"9,7\"","ID_USUARIO_ALTA_INT":"3","FECHA_ALTA_FORMATO_DAT":"2014-09-18 07:20:42","ID_USUARIO_MOD_INT":null,"FECHA_MOD_FORMATO_DAT":null},{"ID_FORMATO_INT":"22","NOMBRE_FORMATO_STR":"7,9\"","ID_USUARIO_ALTA_INT":"3","FECHA_ALTA_FORMATO_DAT":"2014-09-18 07:21:04","ID_USUARIO_MOD_INT":null,"FECHA_MOD_FORMATO_DAT":null},{"ID_FORMATO_INT":"23","NOMBRE_FORMATO_STR":"11\"","ID_USUARIO_ALTA_INT":"3","FECHA_ALTA_FORMATO_DAT":"2014-09-18 07:22:40","ID_USUARIO_MOD_INT":null,"FECHA_MOD_FORMATO_DAT":null},{"ID_FORMATO_INT":"24","NOMBRE_FORMATO_STR":"13\"","ID_USUARIO_ALTA_INT":"3","FECHA_ALTA_FORMATO_DAT":"2014-09-18 07:22:44","ID_USUARIO_MOD_INT":null,"FECHA_MOD_FORMATO_DAT":null},{"ID_FORMATO_INT":"25","NOMBRE_FORMATO_STR":"15\"","ID_USUARIO_ALTA_INT":"3","FECHA_ALTA_FORMATO_DAT":"2014-09-18 07:22:49","ID_USUARIO_MOD_INT":null,"FECHA_MOD_FORMATO_DAT":null},{"ID_FORMATO_INT":"26","NOMBRE_FORMATO_STR":"21,5\"","ID_USUARIO_ALTA_INT":"3","FECHA_ALTA_FORMATO_DAT":"2014-09-18 07:23:11","ID_USUARIO_MOD_INT":null,"FECHA_MOD_FORMATO_DAT":null},{"ID_FORMATO_INT":"27","NOMBRE_FORMATO_STR":"27\"","ID_USUARIO_ALTA_INT":"3","FECHA_ALTA_FORMATO_DAT":"2014-09-18 07:23:14","ID_USUARIO_MOD_INT":null,"FECHA_MOD_FORMATO_DAT":null}
]
The issue is that you're building your SQL withstringWithFormat. That is a practice that is susceptible to this sort of problem. Instead, use ? placeholders in your SQL and then use sqlite3_bind_text to bind values to the ? placeholders. See the sqlite3_bind_text() help for more information.
For example, you might:
const char *insert_stmt = "INSERT INTO FORMATOS (ID, NOMBRE) VALUES (?, ?)";
if (sqlite3_prepare_v2(dieneDB, insert_stmt, -1, &statement, NULL) != SQLITE_OK) { // prepare SQL
NSLog(#"prepare error: %s", sqlite3_errmsg(dieneDB));
} else {
if (sqlite3_bind_text(statement, 1, idStr, -1, NULL) != SQLITE_OK) { // bind 1
NSLog(#"bind idStr error: %s", sqlite3_errmsg(dieneDB));
} else if (sqlite3_bind_text(statement, 2, nameStr, -1, NULL) != SQLITE_OK) { // bind 2
NSLog(#"bind nameStr error: %s", sqlite3_errmsg(dieneDB));
} else if (sqlite3_step(statement) != SQLITE_DONE) { // perform SQL
NSLog(#"step error: %s", sqlite3_errmsg(dieneDB));
} else {
NSLog(#"Guardado Formatos correctamente");
}
sqlite3_finalize(statement);
}
I just typed this in, so please forgive any typos, but hopefully it illustrates the idea.
Note, I also (a) check all of these return codes; (b) log the error if any; and (c) finalize the statement when done.

error: near "?": syntax error using sqlite and obj-c

After a suggestion on here I have tried to bind the values being passed into my queries, but I keep getting the syntax error: error: near "?": can someone explain why please?
NSString *sqLiteDb = [[NSBundle mainBundle] pathForResource:#"banklist" ofType:#"sqlite3"];
if(sqlite3_open([sqLiteDb UTF8String], &_database) == SQLITE_OK)
{
{
// prep statement
sqlite3_stmt *statement;
NSString *querySQL = #"UPDATE ? SET recipe_name=? WHERE cell_id=?";
NSLog(#"query: %#", querySQL);
const char *query_stmt = [querySQL UTF8String];
// preparing a query compiles the query so it can be re-used.
sqlite3_prepare_v2(_database, query_stmt, -1, &statement, NULL);
sqlite3_bind_text(statement, 1, [del.dayName UTF8String], -1, SQLITE_STATIC);
sqlite3_bind_text(statement, 2, [info.name UTF8String], -1, SQLITE_STATIC);
sqlite3_bind_int(statement, 1, del.tableRowNumber);
// process result
if (sqlite3_step(statement) != SQLITE_DONE)
{
NSLog(#"error: %s", sqlite3_errmsg(_database));
}
sqlite3_finalize(statement);
}
{
// prep statement
sqlite3_stmt *statement;
NSString *querySQL = #"UPDATE ? SET recipe_id = (SELECT key FROM recipes WHERE name = ?.recipe_name)";
NSLog(#"query: %#", querySQL);
const char *query_stmt = [querySQL UTF8String];
// preparing a query compiles the query so it can be re-used.
sqlite3_prepare_v2(_database, query_stmt, -1, &statement, NULL);
sqlite3_bind_text(statement, 1, [del.dayName UTF8String], -1, SQLITE_STATIC);
sqlite3_bind_text(statement, 2, [del.dayName UTF8String], -1, SQLITE_STATIC);
// process result
if (sqlite3_step(statement) != SQLITE_DONE)
{
NSLog(#"error: %s", sqlite3_errmsg(_database));
}
sqlite3_finalize(statement);
}
}
sqlite3_close(_database);
You use sqlite3_bind_xxx for values in your SQL, but not for table names. You have to use stringWithFormat for the table names and sqlite3_bind_xxx for the values.
You need to bind a value for each ? in the query. The 2nd parameter to the sqlite3_bind_xxx function is the index number. These are 1-based indexes.
In you 1st query you bind a value to the 1st ? two times. You probably need to change the sqlite3_bind_int call to pass 3 as the index instead of 1.
sqlite3_bind_int(statement, 3, del.tableRowNumber);
One other possible issue is your use of sqlite3_bind_text for the table name. This will put the table name in quotes. As suggested by Rob, you should use a string format to apply the table name but use sqlite3_bind_xxx for actual values you need in your query.

SQLStatement is getting rejected

I'm trying to insert a user note into a sqliteDB through this method but for some reason, its not passing this if statement...
if(sqlite3_prepare_v2(database, sqlStatement, -1, &compiledStatement, NULL) == SQLITE_OK){}
I'm not sure but I think my SQLStatement is getting rejected or some reason.
(void) insertQuickNoteInDataBase:(NSString *)name :(NSString *)note{
sqlite3 * database;
if(sqlite3_open([databasePath UTF8String], &database) == SQLITE_OK) {
const char *sqlStatement = "insert into detail(QuickNote) values (?), where name = ?";
sqlite3_stmt *compiledStatement;
if(sqlite3_prepare_v2(database, sqlStatement, -1, &compiledStatement, NULL) == SQLITE_OK) {
sqlite3_bind_text(compiledStatement, 8, [note UTF8String], -1, SQLITE_TRANSIENT);
sqlite3_bind_text(compiledStatement, 2, [name UTF8String], -1, SQLITE_TRANSIENT);
if(SQLITE_DONE != sqlite3_step(compiledStatement))
NSAssert1(0, #"Error while inserting data. '%s'", sqlite3_errmsg(database));
}
sqlite3_finalize(compiledStatement);
}
sqlite3_close(database);
}
You need to log the error using sqlite3_errmsg. But the problem is most likely the comma in the query as well as the where clause. Insert statements should not have a where clause. Perhaps you mean to use an update:
"UPDATE detail SET QuickNote = ? WHERE name = ?"
Also, your calls to sqlite3_bind_xxx need to have the proper indexes. The bind indexes start at 1 and go up. You are using 8 then 2. You want 1 then 2.

Resources