我知道這可能是一個非常愚蠢的錯誤,但我幾乎一直坐在幾個小時的盯着幾行代碼,通過文檔運行,我仍然無能爲力,爲什麼會發生這種情況:最後一個參數覆蓋了SQLite綁定中的以前的參數
我正在爲C++ 11中的SQLite C API編寫一個便捷包裝類。建立與數據庫的連接時,功能sql
準備一個語句,必要時將參數綁定到該語句,然後執行它。準備和執行工作正常,綁定一個參數工作正常,但如果我想綁定多個參數,所有值將始終設置爲列表中的最後一個參數。
的sql
功能如下:
template <typename... Args>
bool sql(const std::string &query, const Args &... args)
{
sql_statement call;
if(sqlite3_prepare_v2(database_, query.data(), -1, &call.statement, nullptr)
!= SQLITE_OK)
{
return false;
}
if(!bind(call.statement, 1, args...)) {
return false;
}
return sqlite3_step(call.statement) == SQLITE_DONE;
}
sql_statement
是sqlite3_stmt
的包裝結構,什麼也不做,但是當它運行的範圍釋放語句。 database_
是工作數據庫的句柄。我不確定,如果這個功能甚至與這個問題有任何關係。作爲肇事者,我想要的是在sql
函數中調用的bind
函數。這裏是:
template <typename T, typename... Args>
bool bind(sqlite3_stmt *statement, int current, const T &first, const Args &... args)
{
std::stringstream ss;
ss << first;
if(sqlite3_bind_text(statement, current,
ss.str().data(), ss.str().length(), SQLITE_STATIC) != SQLITE_OK)
{
return false;
}
return bind(statement, current+1, args...);
}
bool bind(sqlite3_stmt *, int) { return true; }
請注意,沒有錯誤,函數返回true。我用各種輸入來調試它;當我調試的bind
函數調用,遞歸正常工作,所以它傳遞函數的值[1] nijansen
和[2] 23
if(!db.sql("INSERT INTO test (name, age) VALUES (?, ?);", "nijansen", 23)) {
std::cerr << db.error() << std::endl;
return 1;
}
:考慮這個例子。 The documentation of the SQLite C API說「最左邊的SQL參數的索引是1」,所以不應該是問題。但是,在數據庫中查詢的結果是:id: 1, name: 23, age: 23
。我真的很感謝在這個問題上的第二次看。