You are doing it wrong.
You should not, ever, write out the parameters in full within the query; but instead you should use bound parameters: Binding Values To Prepared Statements.
The main advantage ? Bound parameters do not have to be escaped, which completely prevents any risk of SQL injections, and also greatly simplifies your life!
Also, prepared statements can be reused for greater efficiency, so let me give a full example.
//
// WARNING: for concision purposes there is no error handling
// and no attempt at making this code even remotely exception-safe.
//
// !!! DO NOT USE IN REAL LIFE !!!
//
void update(std::map<int, std::string> const& blobs) {
// 1. Prepare statement
sqlite3_stmt *stmt;
sqlite3_prepare(db,
"update tablename set column = ? where index = ?",
-1, // statement is a C-string
&stmt,
0 // Pointer to unused portion of stmt
);
// 2. Use statement as many times as necessary
for (auto const& pair: blobs) {
int const index = pair.first;
std::string const& blob = pair.second;
// 2.1 Bind 1st parameter
sqlite3_bind_text(stmt,
1, // 1-based index: 1st parameter
blob.data(),
blob.size(),
0 // no need for sqlite to free this argument
);
// 2.2 Bind 2nd parameter
sqlite3_bind_int(stmt,
2, // 1-based index: 2nd parameter
index
);
// 2.3 Execute statement
sqlite3_step(stmt);
// 2.4 Reset bindings
sqlite3_reset(stmt);
}
// 3. Free prepared query
sqlite3_finalize(stmt);
} // update
Note: you can of course keep the prepared statement around for an even longer time.