How to properly escape single quotes in SQLite insert statement - iOS - 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
}
}

Related

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.

ios - sqlite retrieved parametrized sql statement

I am using the following code to create an sql statement for sqlite in ios.
if(addStmt == nil) {
const char *sql = "insert into product(product_id, product_name,quantity) Values(?, ?, ?)";
if(sqlite3_prepare_v2(database, sql, -1, &addStmt, NULL) != SQLITE_OK)
NSAssert1(0, #"Error while creating add statement. '%s'", sqlite3_errmsg(database));
}
sqlite3_bind_int(addStmt, 1, 12 );
sqlite3_bind_text(addStmt, 2, [#"iphone" UTF8String], -1, SQLITE_TRANSIENT);
sqlite3_bind_int(addStmt, 3, 3 );
const char *sqlSt=sqlite3_sql(addStmt);
NSString *str=[NSString stringWithFormat:#"%s",sqlSt];
I get
insert into product(product_id, product_name,quantity) Values(?, ?, ?)
as output.
How can I get something like
insert into product(product_id, product_name,quantity) Values(12, "iphone",3) ?
SQLite does not have any mechanism to read back the values of parameters.

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.

How to store data in database(sqlite)

On iOS, I want store user data in database using sqlite. For that design .Xib file username, password, DOB as text fields and take button, after fill all text fields when click the button all the data is stored in database.
I assume you already know how outlets work and how to get information from UI elements.
SQLite part. SQLite is very easy. You need to have an INSERT query, like this:
char *query = "INSERT INTO myTable (field1, field2) VALUES (?, ?)";
sqlite3_stmt *statem;
sqlite3_prepare_v2(myDB, query, -1, &statem, NULL);
sqlite3_bind_text(statem, 1, [[field1 text] UTF8String], -1, SQLITE_STATIC);
sqlite3_bind_text(statem, 2, [[field1 test] UTF8String], -1, SQLITE_STATIC);
do {
int status = sqlite3_step(statem);
} whlie (status != SQLITE_DONE && status != SQLITE_ERROR);
You should set up the DB first but this can all be found in the documentation.

Resources