How to insert string that contains " character in sqlite ios - ios

i am using following code but sqlite giving me error
NSArray* a = [NSArray arrayWithObjects:
#"\""
#"\\ \"",
nil];
quantity=[quantity stringByReplacingOccurrencesOfString:[a objectAtIndex:0 ] withString:[a objectAtIndex:1]];
queryString = [NSString stringWithFormat:#"INSERT INTO SHOPINGLIST (QUANTITY) VALUES (\"%#\")",quantity];
it gives error that:- near "diax1": syntax error in query INSERT INTO SHOPINGLIST
original quantity is =1 slice,medium(4-1/2"diax1/8"thick)

To insert special characters in SQLite in iOS, use placeholders like (also please check which special characters are allowed in Sqlite):
queryString = #"INSERT INTO SHOPINGLIST (QUANTITY) VALUES (?)";
sqlite3_stmt *compiledStatement;
if(sqlite3_prepare_v2(database, queryString, -1, &compiledStatement, NULL) == SQLITE_OK) {
sqlite3_bind_text(compiledStatement, 1, [quantity UTF8String], -1, SQLITE_TRANSIENT);
// Use sqlite3_bind_text for string values. For other type of values, check sqlite documentation.
// .... And So on.
}

for double value, use this:-
sqlite3_bind_double(compiledStatement, 1, [quantity UTF8String], -1, SQLITE_TRANSIENT);

Related

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.

How to properly escape single quotes in SQLite insert statement - iOS

I have an insert statement for my sqlite table that contains apostrophes in the values.
NSString *sqlInsert = [NSString stringWithFormat:#"insert into myTable (_id, name, area, title, description, url) VALUES (%i, '%#', '%#', '%#', '%#', '%#')", tempObject.ID, tempObject.name, tempObject.area, tempObject.title, tempObject.description, tempObject.url];
The results of that string is this
insert into myTable (_id, name, area, title, description, url) VALUES (0, 'John Smith', 'USA', 'Programmer', 'John Smith is a programmer. He programs a lot. John Smith's duty is to program. He loves it. His dog's name is Billy.', 'www.google.com')
When I try to insert that into the table, I get a syntax error near "s". I want to properly escape the apostrophes. How would I go about doing that? Thanks, any insight is appreciated!
Edit: We have solved our issue. We had entered some single quotes (') into our strings where we really wanted curly single quotes. The curly single quotes do not mess with the SQLite insert statements. For those who have this problem, you could possibly use single curly quotes instead of regular single quotes. This may not be possible in your circumstances, but for some it could be a simple solution.
The issue is your data contains single quote in it. You have two option to overcome this.
Escape ' with \'
Use sqlite3_bind_xxx() method for binding the values ( I prefer this method). You can do it like:
NSString *sqlInsert = #"insert into myTable (_id, name, area, title, description, url) VALUES (?, ?, ?, ?, ?, ?)";
if (sqlite3_open([yourDBPath UTF8String], &yourDB) == SQLITE_OK)
{
if (sqlite3_prepare_v2(yourDB, sql, 1, &stmt, NULL) == SQLITE_OK)
{
sqlite3_bind_int(stmt, 1, tempObject.ID);
sqlite3_bind_text(stmt, 2, [tempObject.name UTF8String], -1, SQLITE_TRANSIENT);
sqlite3_bind_text(stmt, 3, [tempObject.area UTF8String], -1, SQLITE_TRANSIENT);
sqlite3_bind_text(stmt, 4, [tempObject.title UTF8String], -1, SQLITE_TRANSIENT);
sqlite3_bind_text(stmt, 5, [tempObject.description UTF8String], -1, SQLITE_TRANSIENT);
sqlite3_bind_text(stmt, 6, [tempObject.url UTF8String], -1, SQLITE_TRANSIENT);
// Execute
}
}

Using NSString/parameters into SQLite statement iOS

I have my code below. My values _emailVaue _passwordValue and _nameValue are taken from UITextFields in my app. I was under the impression that passing these values into parameters in my SQLite code would allow me to have special characters in those values such as double quotation marks ( " ), however, if I put them in, the SQLite crashes. Is there something I'm doing wrong?
I'm aware that it's probably best to use something like FMDB, but I was hoping that there might be a quicker fix to get me through an upcoming demo.
I'd appreciate any help, thanks!
if (sqlite3_open(dbpath, &_contactDB) == SQLITE_OK)
{
NSString *insertSQL = [NSString stringWithFormat:
#"INSERT INTO CONTACTS (email, password, name) VALUES (\"%#\", \"%#\", \"%#\")",
_emailValue, _passwordValue, _nameValue];
NSLog(insertSQL);
const char *insert_stmt = [insertSQL UTF8String];
sqlite3_prepare_v2(_contactDB, insert_stmt,
-1, &statement, NULL);
if (sqlite3_step(statement) == SQLITE_DONE)
{
} else {
}
sqlite3_finalize(statement);
sqlite3_close(_contactDB);
}
I hope it's OK to answer my own question if it seems to work. Hopefully someone will find it useful. Would appreciate any feedback on where I might be going wrong.
sqlite3_stmt *statement;
const char *dbpath = [_databasePath UTF8String];
const char *insertSQL;
if (sqlite3_open(dbpath, &_contactDB) == SQLITE_OK)
{
insertSQL = "INSERT INTO CONTACTS (email, password, name) VALUES (?, ?, ?)";
if(sqlite3_prepare_v2(_contactDB, insertSQL, -1, &statement, NULL) == SQLITE_OK)
{
sqlite3_bind_text(statement, 1, [_emailValue UTF8String], -1, SQLITE_TRANSIENT);
sqlite3_bind_text(statement, 2, [_passwordValue UTF8String], -1, SQLITE_TRANSIENT);
sqlite3_bind_text(statement, 3, [_nameValue UTF8String], -1, SQLITE_TRANSIENT);
}
if (sqlite3_step(statement) == SQLITE_DONE)
{
//worked
} else {
//didn't work
}
sqlite3_finalize(statement);
sqlite3_close(_contactDB);
}
I'll try to explain what happened with your code and how it could be improved so that the crash would not occur. I totally agree with the usage of bound arguments, this answer is posted only as it represents an answer to how your crash can be fixed, and might help people that don't have the time to switch to bound statements.
Here's what happened:
sqlite3_prepare_v2() failed as your query string was invalid due to the fact that your strings contained the " characted
due to the above, statement was either NULL or contained a garbage value
sqlite3_step() crashed as an invalid pointer was passed as argument.
Here's the fix:
escape all your strings, by replacing " by \", this will generate a valid query; if you were using ' in your query, then you would have to replace ''s by \'
Example for email:
NSString *escapedEmail = [_emailValue stringByReplacingOccurrencesOfString:#"\"" withString:#"\\\""];
even if you're sure the query is correct, is still mandatory to check the result of sqlite3_prepare_v2() before using the statement in any other sqlite calls.
As a general note, you need to code very defensively when dealing with C API's as C doesn't forgive you if you forget to check for NULL pointers. Objective-C is more soft, as it allows you to send messages to nil objects.

iOS: How to insert Special like " or ' character in sqlite

I have a NSString variable that includes some characters " and '.
So, how can I use it as a parameter to insert into table in Sqlite3?
Thanks for helping :)
Escape the quote with 2 quotes. Doublequote needs no replacement
''
SQLFiddle demo
To avoid formatting problems, use a parameter to pass the string into the SQL statement:
NSString *str = #"some characters \" and \'";
const char *sql = "INSERT INTO MyTable(Name) VALUES(?)";
sqlite3_stmt *stmt;
if (sqlite3_prepare_v2(db, sql, -1, &stmt, NULL) == SQLITE_OK) {
sqlite3_bind_text(stmt, 1, [str UTF8String], -1, SQLITE_TRANSIENT);
if (sqlite3_step(stmt) != SQLITE_DONE) {
NSLog(#"SQL execution failed: %s", sqlite3_errmsg(db));
}
} else {
NSLog(#"SQL prepare failed: %s", sqlite3_errmsg(db));
}
sqlite3_finalize(stmt);
You can init the NSString with the special character by put the \ character before it.
For example:
NSString *string = #"This is \" and this is \'";
I would replace the caracter automatically:
NSString *stringFromExternalDatabase = #"Capital of Chad is N'Djamena";
[stringFromExternalDatabase stringByReplacingOccurrencesOfString:#"'" withString:#"\'"];
and then would place stringFromExternalDatabase in a table.
When you retreive the stringFromExternalDatabase from the database, you do the other operation:
[stringFromExternalDatabase stringByReplacingOccurrencesOfString:#"\'" withString:#"'"];

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.

Resources