C ++ SQLite3没有使用预准备语句删除

时间:2017-05-16 19:31:13

标签: c++ sqlite prepared-statement

我在C ++中有以下代码来删除不在矢量ID中的所有ID。打印应该删除的ID,但由于ID绑定,DELETE似乎失败了。 (当我从语句中删除ID并仅绑定引用时,它运行良好)。

这就是数据库的创建方式:

CREATE TABLE IF NOT EXISTS Files (
    ID LONGTEXT DEFAULT NULL,
    Reference LONGTEXT NOT NULL,
    FilePath LONGTEXT PRIMARY KEY NOT NULL,
    ProcessedOn LONGTEXT NOT NULL)

删除正确ID的代码:

rc = sqlite3_prepare_v2(db, "SELECT ID FROM Files WHERE Reference=? AND ID IS NOT NULL", -1, &stmt, 0);
sqlite3_bind_text(stmt, 1, Settings["Reference"].c_str(), Settings["Reference"].length(), 0);
CheckDBError(rc);
rc = sqlite3_step(stmt);
sqlite3_stmt* stmt2;
int rc2 = sqlite3_prepare_v2(db, "DELETE FROM Files WHERE ID=? AND Reference=?", -1, &stmt2, 0);
CheckDBError(rc2);
while(rc == SQLITE_ROW) {
    string IDToCheck = (const char*)sqlite3_column_text(stmt, 0);
    cout << "Checking: " << IDToCheck << endl;
    if (find(IDs.begin(), IDs.end(), IDToCheck) == IDs.end()) {
        cout << "Delete " << IDToCheck << endl;

        //SHOWS ME THE CORRECT ID's BUT THE DELETE IS NOT WORKING. THE 
        //STATEMENT IS EXECUTED PROPERLY WHEN I ONLY USE IT WITH BOUND
        //REFERENCE, SO BINDING the IDToCheck GOES WRONG?

        sqlite3_bind_text(stmt2, 1, IDToCheck.c_str(), IDToCheck.length(), 0);
        sqlite3_bind_text(stmt2, 1, Settings["Reference"].c_str(), Settings["Reference"].length(), 0);
        rc2 = sqlite3_step(stmt2);
        }
    rc = sqlite3_step(stmt);
    }
sqlite3_finalize(stmt);
sqlite3_finalize(stmt2);

1 个答案:

答案 0 :(得分:1)

sqlite3_bind_text() documentation说:

  

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

您没有使用显式析构函数释放的动态缓冲区,因此您无法使用函数指针。 c_str()返回的缓冲区不是非托管缓冲区,因此您无法使用SQLITE_STATIC。 所以你必须使用SQLITE_TRANSIENT

此外,您必须检查错误(请检查rc2,然后致电sqlite3_errmsg()

此外,您需要reset语句才能再次执行它。