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

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:#"'"];

Related

How to execute two insert query in single statement in sqlite3 [duplicate]

This question already has an answer here:
Delete multiple tables from a single query by separating from semicolon
(1 answer)
Closed 7 years ago.
I am trying to insert the values in two different tables in a single statement, first insert query in working second query is not working.
sqlite3_stmt * statement= NULL;
const char *dbpath =[databasePath UTF8String];
if (sqlite3_open(dbpath, &mySqliteDB)== SQLITE_OK)
{
for (PostObject * post in in_PostObject)
{
**query**
NSString * postSql =[NSString stringWithFormat:#"insert or ignore into %#_post (postid,data,active) values (\"%#\",?,\"%d\");",tblPrefix,post.post_ID,post.active];
/*Appending First query with second query*/
NSString * insertSQl =[postSql stringByAppendingString:[NSString stringWithFormat:#" insert into %#_forumuser (uid,utype,name) values (1,'parent','javid');",tblPrefix]];
NSLog(#"%#",insertSQl);
const char * insert_stmt=[insertSQl UTF8String];
sqlite3_prepare_v2(mySqliteDB, insert_stmt, -1, &statement, NULL);
sqlite3_bind_text(statement, 1, [post.jsonData UTF8String], -1, SQLITE_TRANSIENT);
if (sqlite3_step(statement)==SQLITE_DONE)
{
success =TRUE;
}
else
{
NSLog(#"DB Error: %s", sqlite3_errmsg(mySqliteDB));
}
}
}
sqlite3_finalize(statement);
sqlite3_close(mySqliteDB);
You need to check the return code from the sqlite3_prepare_v2 to make sure there aren't any problems.
Also you shouldn't need to open and close the database for each statement you want to execute, there you could process them as 2 statements
if(sqlite3_prepare_v2(mySqliteDB, insert_stmt,-1, &statement, NULL) != SQLITE_OK) {
NSLog(#"%s Prepare failure '%s' (%1d)", __FUNCTION__, sqlite3_errmsg(db), sqlite3_errcode(db));
}

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 insert string that contains " character in sqlite 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);

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.

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