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

C++ SQLite3 not deleting with prepared statement

本文关键字:语句 删除 SQLite3 C++      更新时间:2023-10-16

我在C++中有以下代码来删除所有不在矢量ID中的ID。将打印应删除的 ID,但由于 ID 绑定,删除似乎失败。(当我从语句中删除 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);

sqlite3_bind_text() 文档说:

BLOB

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

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

此外,您必须检查错误(检查rc2,并调用sqlite3_errmsg()。

此外,您需要先重置语句,然后才能再次执行它。