Как добавлять новую запись в бд, считанную из введенной переменной SQLite3
static int insertData(const char* s) {
sqlite3* DB;
char* messageError;
string InpLogin;
string InpPassword;
cout << "Login: ";
cin >> InpLogin;
cout << "Password: ";
cin >> InpPassword;
string sql("INSERT INTO Users (Login, Password) VALUES('Admin', '123qwer');");
// Как в значения подставлять переменные InpLogin и InpPassword
int exit = sqlite3_open(s, &DB);
/* An open database, SQL to be evaluated, Callback function, 1st argument to callback, Error msg written here */
exit = sqlite3_exec(DB, sql.c_str(), NULL, 0, &messageError);
if (exit != SQLITE_OK) {
cerr << "Error in insertData function." << endl;
sqlite3_free(messageError);
}
else
cout << "Records inserted Successfully!" << endl;
return 0;
}
Как в значения подставлять переменные InpLogin и InpPassword?
Ответы (1 шт):
Наиболее правильный способ подставить переменные в запрос — это использовать подготовленные выражение. Одним из преимуществ данного способа является защита от sql-инъекций.
В строке sql мы создаём запрос, где в месте, куда мы желаем подставить переменные, поставлены выражения формата ?NNN. Здесь NNN индекс связываемой переменной, начинающийся с единицы. В данном случае это будет ?1 и ?2.
С помощью метода sqlite3_prepare_v2 мы создаём экземпляр данного выражения, которое будет хранится в sqlite3_stmt.
Далее, с помощью метода sqlite3_bind_text мы подставляем в запрос значения связанных переменных. В нём указывается экземпляр выражения sqlite3_stmt*, индекс связываемой переменной, значение переменной (в нашем случае текст). Последним аргументом идёт индикатор времени жизни подаваемого на вход объекта. В случае, если гарантируется, что объект будет существовать до завершения работы с выражением, используется SQLITE_STATIC, в противном случае SQLITE_TRANSIENT заставит метод sqlite3_bind_text скопировать выражение для дальнейшего использования.
Выражение со всеми подготовленными переменными выполняется при помощи sqlite3_step.
Перед повторным использованием подготовленного выражения необходимо вызвать sqlite3_reset.
Больше подробностей и прочие методы sqlite3_bind_* можно найти здесь
sqlite3_stmt* pStmt = nullptr;
std::string sql("INSERT INTO Users(Login, Password) VALUES (?1, ?2);");
result = sqlite3_prepare_v2(db, sql.c_str(), -1, &pStmt, nullptr);
if (result != SQLITE_OK) {
fprintf(stderr, "Prepare error\n");
return -1;
}
result = sqlite3_bind_text(pStmt, 1/*?1*/, InpLogin.c_str(), -1, SQLITE_TRANSIENT);
if (result != SQLITE_OK) {
fprintf(stderr, "Bind text error\n");
}
result = sqlite3_bind_text(pStmt, 2/*?2*/, InpPassword.c_str(), -1, SQLITE_TRANSIENT);
if (result != SQLITE_OK) {
fprintf(stderr, "Bind text error\n");
}
result = sqlite3_step(pStmt);
if ( result != SQLITE_DONE ) {
fprintf(stderr, "Execution error\n");
}
sqlite3_reset( pStmt );
sqlite3_clear_bindings( pStmt );
