2017-05-16 4 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

あなたはあなたが彼は 'sqlite3_bind_text()'関数の値を期待していましたか? – MrEricSir

答えて

1

sqlite3_bind_text() documentationは言う:

BLOBへの5番目の引数文字列バインディングインターフェイスは、SQLiteが処理を終えた後にBLOBまたは文字列を破棄するために使用されるデストラクタです。デストラクタは、APIをバインドする呼び出しが失敗した場合でも、BLOBまたは文字列を破棄するために呼び出されます。 5番目の引数が特殊な値SQLITE_STATICの場合、SQLiteは情報が静的で管理されていない空間にあるとみなし、解放する必要はありません。 5番目の引数の値がSQLITE_TRANSIENTの場合、SQLiteはsqlite3_bind _ *()ルーチンが戻る前に、データの専用コピーを直ちに作成します。

明示的なデストラクタで解放される動的バッファがないため、関数ポインタは使用できません。 c_str()によって返されたバッファはアンマネージドではないため、SQLITE_STATICは使用できません。 SQLITE_TRANSIENTを使用する必要があります。

また、あなたがrc2をチェックし、sqlite3_errmsg()を呼び出し(エラーをチェックする。

を持っている。また、あなたはそれをもう一度実行する前に声明をresetする必要があります。

+0

'SQLITE_TRANSIENT'を追加すると、最初のdelete文だけが実行されますか? –

+1

?なぜそれを求めているのですか?それはあなたが観察したことですか? –

+0

はい...私はアプリケーションを実行し、最初のdelete文だけが実行されます。しかし、 'sqlite3_bind_int64'でIDをバインドすると、同じ状況が発生し、最初のdelete文だけが実行されます –

関連する問題