If you use the SQLite C API like this
char query[256];
snprintf(query, sizeof(query),
"SELECT * FROM users WHERE username = '%s'", username);
int rc = sqlite3_exec(db, query, NULL, NULL, &err_msg);
and someone enters Robert'; DROP Table Students;-- as username, it deletes the table Students.
const char *sql = "SELECT * FROM users WHERE username = ?";
int rc = sqlite3_prepare_v2(db, sql, -1, &stmt, NULL);
if (rc != SQLITE_OK) {
fprintf(stderr, "Failed to prepare statement\n");
return;
}
sqlite3_bind_text(stmt, 1, username, -1, SQLITE_STATIC);
Using this "prepared statement" and "bind", your code is secured against such SQL injection attacks.