当绑定发生在另一个函数中时,Sqlite 找不到行 _only_

Sqlite doesn't find row _only_ when binding takes places in another function

本文关键字:Sqlite 找不到 only 绑定 函数 另一个      更新时间:2023-10-16

所以我给自己写了一个小包装函数来为我做一个准备好的语句:

sqlite3_stmt* Gladiateur::run_query_unfinalized(string query, vector<string> inputs){
    sqlite3_stmt *statement;
    // Prepare SQL
    sqlite3_prepare_v2(db, query.c_str(), -1, &statement, NULL);
    // Bind parameter
    sqlite3_bind_text(statement, 1, inputs[0].c_str(), -1, NULL);
    return statement;
}

通常它会通过输入向量并绑定所有字符串,但我简化了代码以找出错误所在。

我还有另一个功能set_list(也简化):

int Gladiateur::set_list (string list_name) {
    vector<string> bind = {list_name};
    sqlite3_stmt *statement = this->run_query_unfinalized("SELECT id FROM lists WHERE name = ? LIMIT 1", bind);
    printf("code %dn", sqlite3_step(statement));
    sqlite3_finalize(statement);
    return 1;
}

我调用set_list,得到"代码 101",这仅意味着没有 SQL 错误,但没有检索到行。不过,我知道存在匹配的行。

奇怪的部分来了:我移动了这条线

sqlite3_bind_text(statement, 1, inputs[0].c_str(), -1, NULL);

到 set_list 函数中,就在 printf 上方,然后写入bind[0]而不是 inputs[0] 。它有效!我得到"代码 100",找到了该行,当我检查时它也给了我正确的 id。

但我想在run_query_unfinalized做所有的绑定......我真的很困惑为什么它不起作用。也许我不能像那样传递statement变量?

sqlite3_bind_text函数的最后一个参数不能为 NULL:

BLOB

和字符串绑定接口的第五个参数是一个析构函数,用于在 SQLite 完成 BLOB 或字符串后释放它。调用析构函数以释放 BLOB 或字符串,即使对绑定 API 的调用失败也是如此。如果第五个参数是特殊值SQLITE_STATIC,则 SQLite 假定信息位于静态的非托管空间中,不需要释放。如果第五个参数的值为 SQLITE_TRANSIENT,则 SQLite 会在 sqlite3_bind_*() 例程返回之前立即创建自己的数据私有副本。

在这种情况下,您需要 SQLITE_TRANSIENT .

Gladiateur::run_query_unfinalized(string query, vector<string> inputs)

vector<string> inputs是一个副本,当函数返回时,它不再存在。

也许您应该将其更改为:

Gladiateur::run_query_unfinalized(const string& query, const vector<string>& inputs)

有了参考,c_str应该生存下来做你想做的事情。