2017-05-16 25 views
0

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

这是DB是如何创建的:

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); 
+2

“似乎失败”“不能正常工作“你能更具体吗? –

+0

好吧,记录不会被删除,但是当我只绑定引用,所以从语句中删除ID =?,它会很好地删除记录,但是当我绑定ID =?再次声明不会删除记录。**所以在我看来,ID的绑定失败** –

+1

您是否使用过调试器来验证您是否传递了t他期望'sqlite3_bind_text()'函数的值? – MrEricSir

回答

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语句,然后才能执行它第二次。

+0

如果我添加'SQLITE_TRANSIENT',只执行第一条删除语句? –

+1

咦?你为什么问这个?那是你观察到的吗? –

+0

是的......我执行应用程序,现在只执行第一条删除语句。但是,当我用'sqlite3_bind_int64'绑定ID时,会出现同样的情况,只执行第一条删除语句 –