Одна строка результата выборки
Не каждый SELECT возвращает много строк.
Иногда нужна одна запись или проверка, что совпадений
нет. Строки все равно читают через sqlite3_step.
Если шаг вернул SQLITE_ROW, текущая строка
доступна - в простом сценарии с уникальным ключом
ее часто одна:
#include <iostream>
#include <sqlite3.h>
int main() {
sqlite3* db = nullptr;
if (sqlite3_open("single_hit.db", &db) != SQLITE_OK) {
std::cerr << sqlite3_errmsg(db) << "\n";
sqlite3_close(db);
return 1;
}
char* err = nullptr;
if (sqlite3_exec(
db,
"CREATE TABLE IF NOT EXISTS tokens ("
"id INTEGER PRIMARY KEY,"
"secret TEXT NOT NULL"
")",
nullptr,
nullptr,
&err
) != SQLITE_OK) {
std::cerr << err << "\n";
sqlite3_free(err);
sqlite3_close(db);
return 1;
}
if (sqlite3_exec(
db,
"INSERT INTO tokens (secret) VALUES ('x-ray')",
nullptr,
nullptr,
&err
) != SQLITE_OK) {
std::cerr << err << "\n";
sqlite3_free(err);
sqlite3_close(db);
return 1;
}
sqlite3_stmt* query = nullptr;
if (sqlite3_prepare_v2(
db,
"SELECT secret FROM tokens WHERE id = ?",
-1,
&query,
nullptr
) != SQLITE_OK) {
std::cerr << sqlite3_errmsg(db) << "\n";
sqlite3_close(db);
return 1;
}
sqlite3_bind_int(query, 1, 1);
if (sqlite3_step(query) == SQLITE_ROW) {
const char* secret =
reinterpret_cast<const char*>(
sqlite3_column_text(query, 0)
);
std::cout << secret << "\n";
}
sqlite3_finalize(query);
sqlite3_close(db);
return 0;
}
Когда условие никому не подошло, первый же шаг
дает SQLITE_DONE вместо SQLITE_ROW.
Это нормальный пустой результат, а не сбой протокола:
#include <iostream>
#include <sqlite3.h>
int main() {
sqlite3* db = nullptr;
if (sqlite3_open("single_hit.db", &db) != SQLITE_OK) {
std::cerr << sqlite3_errmsg(db) << "\n";
sqlite3_close(db);
return 1;
}
sqlite3_stmt* query = nullptr;
if (sqlite3_prepare_v2(
db,
"SELECT secret FROM tokens WHERE id = ?",
-1,
&query,
nullptr
) != SQLITE_OK) {
std::cerr << sqlite3_errmsg(db) << "\n";
sqlite3_close(db);
return 1;
}
sqlite3_bind_int(query, 1, 99);
if (sqlite3_step(query) == SQLITE_ROW) {
const char* secret =
reinterpret_cast<const char*>(
sqlite3_column_text(query, 0)
);
std::cout << secret << "\n";
} else {
std::cout << "empty\n";
}
sqlite3_finalize(query);
sqlite3_close(db);
return 0;
}
Создайте таблицу passes в gate.db,
вставьте пропуск "vip-1" и выведите его,
если выборка по id 1 нашла строку.
Запросите id 100 и выведите
"none", когда sqlite3_step
не вернул SQLITE_ROW.