我知道这可能是一个非常愚蠢的错误,但我几乎一直坐在几个小时的盯着几行代码,通过文档运行,我仍然无能为力,为什么会发生这种情况:最后一个参数覆盖了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
。我真的很感谢在这个问题上的第二次看。