Как параметры привязки работают в SQLite3 (с минимальным примером)?
Кто-то рекомендовал использовать привязку параметров в SQLite, чтобы ускорить повторяющиеся запросы. Тем не менее, это не работает, если у меня есть несколько параметров для привязки. Я не вижу своей ошибки. Все функции SQLite возвращаются с SQLITE_OK ...
Ниже я написал минимальный пример. Он создает таблицу, делает три записи, а затем запрашивает два раза, один раз с одним параметром связывания и один раз с двумя. Первый раз возвращается с одним результатом, который является правильным. Второй возвращается с нулевым результатом, а sqlite3_step () возвращается с 101 (SQLITE_DONE). Почему он также не возвращает один результат?
#include <vector>
#include <sqlite3.h>
int main(int argc, char * argv[])
{
sqlite3 * pDB;
int iReturn = sqlite3_open("./Test.db", &pDB);
if (iReturn != SQLITE_OK) {
return 1;
}
// create table
{
std::string str = "CREATE TABLE Names(ID INTEGER PRIMARY KEY, Name VARCHAR(30))";
iReturn = sqlite3_exec(pDB, str.c_str(), NULL, NULL, NULL);
if (iReturn != SQLITE_OK) {
sqlite3_close(pDB);
return 1;
}
}
// insert data using binding
{
std::string str = "INSERT INTO Names(Name) VALUES(?)";
sqlite3_stmt * pStmt = nullptr;
iReturn = sqlite3_prepare_v2(pDB, str.c_str(), str.size() + 1, &pStmt, nullptr);
if (iReturn != SQLITE_OK) {
sqlite3_close(pDB);
return 1;
}
printf("The statement %s has %d parameter(s).\n", str.c_str(), sqlite3_bind_parameter_count(pStmt));
std::vector<std::string> vecNames;
vecNames.push_back("Smith");
vecNames.push_back("Morpheus");
vecNames.push_back("Neo");
for (unsigned int i = 0, iEnd = vecNames.size(); i != iEnd; ++i)
{
iReturn = sqlite3_bind_text(pStmt, 1, vecNames[i].c_str(), vecNames[i].size() + 1, nullptr);
if (iReturn != SQLITE_OK) {
return 1;
}
if (sqlite3_step(pStmt) != SQLITE_DONE) {
sqlite3_finalize(pStmt);
sqlite3_close(pDB);
return 1;
}
sqlite3_reset(pStmt);
sqlite3_clear_bindings(pStmt);
}
}
// query using one bind parameter
{
sqlite3_stmt * pStmt = nullptr;
string str = "SELECT ID FROM Names WHERE Name=?1";
iReturn = sqlite3_prepare_v2(pDB, str.c_str(), str.size() + 1, &pStmt, nullptr);
if (iReturn != SQLITE_OK) {
return 1;
}
printf("The statement %s has %d parameters(s).\n", str.c_str(), sqlite3_bind_parameter_count(pStmt));
// fourth parameter is length = position of \0
iReturn = sqlite3_bind_text(pStmt, 1, "Neo", 3, NULL);
if (iReturn != SQLITE_OK) {
return 1;
}
vector<string> vecResults;
char cBuffer[1024];
string strBuffer;
while (sqlite3_step(pStmt) == SQLITE_ROW)
{
sprintf(cBuffer, "%s", sqlite3_column_text(pStmt, 0));
strBuffer = cBuffer;
vecResults.push_back(strBuffer);
}
sqlite3_finalize(pStmt);
printf("Found %d results.\n", vecResults.size());
for (unsigned int i = 0, iEnd = vecResults.size(); i != iEnd; ++i)
{
printf("%d: %s\n", i, vecResults[i].c_str());
}
}
// query using two bind parameters
{
sqlite3_stmt * pStmt = nullptr;
string str = "SELECT ID FROM Names WHERE Name=?1 AND ID=?2";
iReturn = sqlite3_prepare_v2(pDB, str.c_str(), str.size() + 1, &pStmt, nullptr);
if (iReturn != SQLITE_OK) {
return 1;
}
printf("The statement %s has %d parameters(s).\n", str.c_str(), sqlite3_bind_parameter_count(pStmt));
// fourth parameter is length = position of \0
iReturn = sqlite3_bind_text(pStmt, 1, "Neo", 3, NULL);
if (iReturn != SQLITE_OK) {
return 1;
}
iReturn = sqlite3_bind_text(pStmt, 2, "3", 2, NULL);
if (iReturn != SQLITE_OK) {
return 1;
}
vector<string> vecResults;
char cBuffer[1024];
string strBuffer;
while (sqlite3_step(pStmt) == SQLITE_ROW)
{
sprintf(cBuffer, "%s", sqlite3_column_text(pStmt, 0));
strBuffer = cBuffer;
vecResults.push_back(strBuffer);
}
sqlite3_finalize(pStmt);
printf("Found %d results.\n", vecResults.size());
for (unsigned int i = 0, iEnd = vecResults.size(); i != iEnd; ++i)
{
printf("%d: %s\n", i, vecResults[i].c_str());
}
}
sqlite3_close(pDB);
return 0;
}