2017-05-16 7 views
0

다음 코드는 C++에서 벡터 ID에없는 모든 ID를 삭제합니다. 삭제해야하는 ID가 인쇄되지만 ID 바인딩으로 인해 DELETE가 실패한 것으로 보입니다. (문에서 ID를 제거하고 참조 만 바인딩하면 잘 작동합니다).C++ SQLite3 준비 문을 사용하여 삭제되지 않음

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는 말한다 :

는 DB가 생성되는 방법입니다 BLOB에

다섯 번째 인수 문자열 바인딩 인터페이스는 SQLite가 BLOB 또는 문자열을 처리 한 후 파기하는 데 사용되는 소멸자입니다. 소멸자는 bind API에 대한 호출이 실패하더라도 BLOB 또는 문자열을 처리하기 위해 호출됩니다. 다섯 번째 인수가 특수한 값인 SQLITE_STATIC이면 SQLite는 정보가 정적 인 관리되지 않는 공간에 있다고 간주하고 해제 할 필요가 없습니다. 다섯 번째 인수에 SQLITE_TRANSIENT 값이 있으면 SQLite는 sqlite3_bind _ *() 루틴이 반환되기 전에 즉시 데이터의 자체 복사본을 만듭니다.

명시 적 소멸자로 해제 된 동적 버퍼가 없으므로 함수 포인터를 사용할 수 없습니다. c_str()에 의해 반환 된 버퍼는 관리되지 않으므로 SQLITE_STATIC을 사용할 수 없습니다. SQLITE_TRANSIENT을 사용해야합니다. 또한

, 당신은 오류 (rc2을 확인하고 sqlite3_errmsg()를 호출합니다.

을 또한, 당신은 당신이 그것을 두 번째로 실행하기 전에 문을 reset해야합니다.

+0

'SQLITE_TRANSIENT'을 추가하면 첫 번째 delete 문만 실행됩니까? –

+1

어? 왜 그걸 묻는거야? 그것은 당신이 관찰 한 것입니까? –

+0

예 ... 이제 응용 프로그램을 실행하고 첫 번째 delete 문만 실행됩니다. 그러나 ID를'sqlite3_bind_int64'로 바인드 할 때 동일한 상황이 발생하여 첫 번째 삭제 명령문 만 실행 –