Как вытащить запись из БД и поместить ее в переменную? Sqlite3 c++
Подскажите как правильнее будет сделать, потому что я SQL только начал активно юзать и в написании запросов не очень силен. Я понял как выводить всю таблицу или отдельные ее записи, но мне нужно как то вытаскивать запись и класть ее в переменную, чтобы уже работать непосредственно с этими данными.
Тут я писал запросы, которые возвращают записи или таблицу
static int selectData(const char* s)
{
sqlite3* DB;
char* messageError;
string sql = "SELECT * FROM Users;";
int exit = sqlite3_open(s, &DB);
exit = sqlite3_exec(DB, sql.c_str(), callback, NULL, &messageError);
if (exit != SQLITE_OK) {
cerr << "Error in selectData function." << endl;
sqlite3_free(messageError);
}
else
cout << "Records selected Successfully!" << endl;
return 0;
}
таблицу и записи я выводил в консоль вот таким образом
static int callback(void* NotUsed, int argc, char** argv, char** azColName)
{
for (int i = 0; i < argc; i++)
{
cout << azColName[i] << ": " << argv[i] << endl;
}
cout << endl;
return 0;
}
Ответы (1 шт):
Через exec/callback
Если Вы хотите использовать callback функцию, то в её первый аргумент void* передаётся четвёртый аргумент функции sqlite3_exec.
Допустим, мы хотим получить пароль на основе логина. Мой запрос выглядит так:
SELECT `Password` FROM `Users` WHERE `Login` = 'test';
Тогда моя callback функция, которая должна записать мне значения пароля в std::string, будет выглядеть примерно так:
static int callback(void *pString, int argc, char **argv, char **azColName){
if (argc>0) {
std::string* str = static_cast<std::string*>(pString);
str->assign(argv[0]);
}
return 0;
}
Здесь я исхожу из того, что знаю индекс искомого столбца (это 0). В зависимости от ситуации можно обрабатывать элементы другим образом.
В коде это будет использоваться так:
std::string sql1("SELECT `Password` FROM `Users` WHERE `Login` = 'test';");
std::string outStr;
result = sqlite3_exec(db, sql1.c_str(), callback, &outStr, &err);
if (result != SQLITE_OK) {
std::cerr << "Error in selectData function." << endl;
sqlite3_free(err);
}
std::cout << "Result:" << outStr << std::endl;
Важно понимать, что функция callback будет вызываться для каждой строки результата, что необходимо учесть при работе с первым аргументом.
Через подготовленные выражения
В большинстве случаев более выгодно использовать подготовленные выражения.
В запросе заменим искомую строку на выражение формата ?NNN, на место которого мы будем подставлять переменную:
SELECT `Password` FROM `Users` WHERE `Login` = ?1;
Переменная pStmt будет хранить указатель на подготовленное выражение sqlite3_stmt*, которое создастся в функции sqlite3_prepare_v2.
Функция sqlite3_bind_text свяжет выражение ?1 с подаваемым ему на вход объектом (в данном случае InpLogin.c_str()). Смотрите ответ на Ваш вопрос или документацию.
Функция sqlite3_step будет возвращать SQLITE_ROW, в случае если возможно получить ещё одну строку из ответа. Т.к. строк может больше одной обрабатываем их в цикле.
Функции группы sqlite3_column_* позволяют получать значения колонки в строке результата на основе подготовленного выражения. В данном случае используем sqlite3_column_text (Она возвращает const unsigned char* поэтому используем reinterpret_cast).
Завершаем работу с подготовленным выражением используя sqlite3_finalize.
std::string InpLogin = "test";
sqlite3_stmt* pStmt = nullptr;
std::string sql2("SELECT `Password` FROM `Users` WHERE `Login` = ?1;");
result = sqlite3_prepare_v2(db, sql2.c_str(), -1, &pStmt, nullptr);
if (result != SQLITE_OK) {
std::cerr << "Prepare error\n";
return -1;
}
result = sqlite3_bind_text(pStmt, 1 /*?1*/, InpLogin.c_str(), -1, SQLITE_TRANSIENT);
if (result != SQLITE_OK) {
std::cerr << "Bind text error\n";
}
while (true) {
result = sqlite3_step(pStmt);
if (result == SQLITE_ROW) {
outStr.assign(reinterpret_cast<const char*>(sqlite3_column_text(pStmt, 0)));
//Работаем со строкой
std::cout << "Result:" << outStr << std::endl;
} else {
break;
}
}
if ( result != SQLITE_DONE ) {
std::cerr << "Execution error\n";
}
sqlite3_finalize(pStmt);
Касательно запроса
Вероятно в Вашем случае следует использовать другой запрос, который сравнил бы значения переменных на стороне БД:
SELECT `Users` FROM `Users` WHERE `Login` = ?1 AND `Password` = ?2;
В случае если он ничего не вернёт, то искомого пользователя с такой парой Login/Password не существует. С аналогичной целью можно запросить количество пользователей с искомой парой Login/Password:
SELECT COUNT(*) FROM `Users` WHERE `Login` = ?1 AND `Password` = ?2;