SQlite3 error: database is locked
-
@MHage sagte in SQlite3 error: database is locked:
Jetzt bin ich schonmal einen Schritt weiter. Jetzt kommt der Fehler: Tabelle old_db.AusgHauptgruppe existiert nicht. Das halte ich für ein Gerücht!
Bist du dir sicher, dass
2020.s3db
an dem Pfad an dem gesucht wird, auch gefunden werden kann? Ich würde es mal testweise mit einem absoluten Pfad versuchen. Wenn sqlite2020.s3db
nicht findet, wird eine leere Datenbank erzeugt, in der die TabelleAusgHauptgruppe
natürlich nicht existiert.
-
Der Gedanke kam mir auch schon einmal. In meinem Quellcode oben findest du bei case 1:
folgende Zeile:os << "PRAGMA database_list;";
Im Rückgabewert stand
0: main KompletterPfad\2021.s3db
2: old_db KompletterPfad\2020.s3dbDaher habe ich den Gedanken wieder verworfen. Wundert mich nur, das der Index 2 und nicht 1 ist...
Übrigens, die Meldung "database locked" kommt immernoch. Irgendwie weiß ich da auch nicht weiter...VG
-
Mittlerweile habe ich herausgefunden, das das Problem mit der locked database mit der Syntax des sql_query's zu tun hat
os << "INSERT INTO main.AusgHauptgruppe(Position, Gruppe, Saldo) " << "SELECT 'Position', 'Gruppe', 'Saldo' FROM 'old_db.AusgHauptgruppe';";
Schreibe ich es so wie hier gezeigt, ist die db nicht mehr locked. Dafür bekomme ich jetzt die Meldung, das die Tabelle old_db.AusgHauptgruppe nicht existiert.
Wenn man den String als ganzes sieht, hat er sogar Recht. Ich denke, aus irgendeinem Grund/ oder meiner Schreibweise ist nicht klar, das ich über old_db eine andere db anspreche....Korrekt "attached" ist sie aber, das habe ich kontrolliert.
-
mir fällt auf die Schnelle auf, dass Du bei
insert into
die Zieltabelle nicht in Hochkomma'
eingefasst hast, die Quelltabelle beifrom
dann aber schon, ist das so korrekt?
-
Es ist für mich immer wieder irgendwie ein Rätselraten, wie nun genau die Schreibweise auszusehen hat. Grundsätzlich ist erstmal alles, was ich schreibe in Frage zustellen...
Ich habe über sie sqlite3.exe aus dem Tools-Archiv das gleiche mal gemacht. Da hat es funktioniert. D.h. weiter database über attach hinzufügen und einzelne Daten aus Tabellen kopieren. Da gab es kein Problem mit locked. Ich habe irgendwie das Gefühl, das die C++ Schnittstelle da eine Besonderheit hat. Sonst kann ich alles, zu jedem Zeitpunkt, egal wie oft, ausführen. Wirklich egal, ob SELECT, INSERT, UPDATE oder DELETE. Noch nicht ein einziges mal Probleme gehabt. Nur jetzt, nach dem hinzufügen einer weiteren db.
Schon eigenartig. ...
-
Ich würde dann mal in einem Testfall den selben SQL Code über das C Interface ausführen, wie über die Kommandozeile.
Also, DB öffnen, andere DB attachen, und einen String mit dem Befehl da rein schieben. Alles unnötige drum herum weg, gleiche Schreibweise im C++ Code wie in der Commandozeile.Bei genauerem hinsehen ist:
@MHage sagte in SQlite3 error: database is locked:
os << "INSERT INTO main.AusgHauptgruppe(Position, Gruppe, Saldo) " << "SELECT 'Position', 'Gruppe', 'Saldo' FROM 'old_db.AusgHauptgruppe';";
auch falsch: Du fügst da immer die String "Position", "Gruppe" und "Saldo" ein, wegen der Anführungszeichen. Dafür brauchst du die andere Tabelle überhaupt nicht.
Versuch mal
os << "INSERT INTO main.AusgHauptgruppe(Position, Gruppe, Saldo) " << "SELECT Position, Gruppe, Saldo FROM old_db.AusgHauptgruppe;";
-
@Schlangenmensch
Ok... neuer Versuch
Habe jetzt wie folgt umgeschriebenvoid TFormMain::CopyTables() { sqlite3 *db; sqlite3_stmt* stmt = 0; char *zErrMsg = 0; int rc; string tmp; ostringstream os; const char *sql_query; char *str; os << AktJahr << ".s3db"; tmp = os.str(); const char *num_char = tmp.c_str(); rc = sqlite3_open(&num_char[0], &db); // Datenbank öffnen for(int i = 0; i < 14; i++) { os.str(""); // reset the string to be empty os.clear(); // clear any error flags that may be set stmt = 0; switch(i) { case 0: os << "ATTACH DATABASE '" << AktJahr-1 << ".s3db' AS old_db;"; break; case 1: os << "INSERT INTO main.AusgHauptgruppe(Position, Gruppe, Saldo) " << "SELECT Position, Gruppe, Saldo FROM old_db.AusgHauptgruppe;"; break; case 2: os << "INSERT INTO main.AusgKto1(Position, Konto) " << "SELECT Position, Konto FROM old_db.AusgKto1;"; break; case 3: os << "INSERT INTO main.AusgKto2(Position, Konto) " << "SELECT Position, Konto FROM old_db.AusgKto2;"; break; case 4: os << "INSERT INTO main.AusgKto3(Position, Konto) " << "SELECT Position, Konto FROM old_db.AusgKto3;"; break; case 5: os << "INSERT INTO main.AusgKto4(Position, Konto) " << "SELECT Position, Konto FROM old_db.AusgKto4;"; break; case 6: os << "INSERT INTO main.AusgKto5(Position, Konto) " << "SELECT Position, Konto FROM old_db.AusgKto5;"; break; case 7: os << "INSERT INTO main.AusgKto6(Position, Konto) " << "SELECT Position, Konto FROM old_db.AusgKto6;"; break; case 8: os << "INSERT INTO main.AusgKto7(Position, Konto) " << "SELECT Position, Konto FROM old_db.AusgKto7;"; break; case 9: os << "INSERT INTO main.AusgKto8(Position, Konto) " << "SELECT Position, Konto FROM old_db.AusgKto8;"; break; case 10: os << "INSERT INTO main.EinKonten(Position, Konto, Saldo) " << "SELECT Position, Konto, Saldo FROM old_db.EinKonten;"; break; case 11: os << "INSERT INTO main.Kontenliste(Position, Konto, Saldo) " << "SELECT Position, Konto, Saldo FROM old_db.Kontenliste;"; break; case 12: os << "INSERT INTO main.Zahlart(Position, Text, vonKto, mitNr) " << "SELECT Position, Text, vonKto, mitNr FROM old_db.Zahlart;"; break; case 13: os << "DETACH DATABASE '" << AktJahr-1 << ".s3db';"; break; default: break; } tmp = os.str(); sql_query = tmp.c_str(); rc = sqlite3_prepare_v2( db, &sql_query[0], -1, &stmt, NULL ); int retVal = sqlite3_step(stmt); if (retVal != SQLITE_DONE) { } sqlite3_reset(stmt); sqlite3_finalize(stmt); } sqlite3_exec(db, "COMMIT TRANSACTION", NULL, NULL, &zErrMsg); sqlite3_close(db); }
Bei case 1: ist der RetVal von sqlite3_step(stmt); 101 SQLITE_DONE. Hier also alles schön!
Bei case 2: ist der RetVal 5 . Entspricht SQLITE_BUSYSagt mir, das die Ausführung von case 2: nicht richtig abgeschlossen wurde.
Alles in Allem schon mal ein Schritt in die richtige Richtung. Immerhin nicht mehr lockedJetzt wäre nur interessant, warum er nicht richtig abgeschlossen hat...
Nachtrag:
Habe folgendes direkt nach dem öffnen der db eingefügtsqlite3_exec(db, "BEGIN TRANSACTION;", NULL, NULL, NULL);
Das hat jetzt bewirkt, das er immer mit Status 101 abschliesst.
Leider steht nur nichts in der db. Also nur so getan als ob....
Vielleicht noch Syntax?
-
BEGIN TRANSACTION
undCOMMIT TRANSACTION
solltest du nicht brauchen.reset
undfinalize
garantieren jeweils, das die implizierte Transaktion abgeschlossen wird. Mitsqlite3_prepare_v2
undfinalize
sollte auch dasreset
überflüssig seinAber auch
finalize
undreset
geben Fehlercodes zurück, die man abfragen könnte. Vlt geht schon vorher was schief.SQLITE_BUSY
spricht eigentlich dafür, dass noch ein anderer Prozess auf die DB zugreift. Hast du vlt dein Programm mehrfach gestartet und hast die DB ausversehen mehrfach geöffnet?
-
@Schlangenmensch
n'abend,Nachdem ich noch einige Stunden an dem Problem gesessen habe, ohne auch nur einen Schritt weiter zu kommen, habe ich mir entschlossen eine kleine Test-App zu machen.
Denn an meinem aktuellen Stand kann ich keinen Fehler mehr finden...
Was soll ich sagen, es hat auf anhieb einwandfrei funktioniert.
Nun gut, in meinem eigentlichen Programm funktioniert es jetzt zwar immer noch nicht, aber nun weiß ich, wo ich weiter suchen muss...
Vielen Dank für eure Hilfe!
-
@MHage Darum ist TDD (https://en.wikipedia.org/wiki/Test-driven_development) the way to go