SQlite3 error: database is locked



  • @manni66
    string hat eine c_str Funktion.... Ja, das ist mir bekannt.
    Stehe dennoch gerade etwas auf dem Schlauch. Wie würdest du es schreiben? Kurzes Beispiel wär nett.

    Tatsächlich haben die Daten einen Zeitstempel. Jedes Jahr eine neue Datendatei anzulegen ist zugegebenermaßen nicht wirklich üblich und meistens wenig Sinnvoll.
    In diesem Fall soll es dem Benutzer die Datensicherung etwas erleichtern. Ich weiß, das es dafür wesentlich elegantere Methoden gibt....



  • @MHage sagte in SQlite3 error: database is locked:

    Wie würdest du es schreiben?

    Wie was schreiben? Welches Problem löst Du denn mit Deinem vector?



  • Alles klar... 🙂
    vector brauch ich überhaupt nicht... Ein ewig lernender....



  • @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 sqlite 2020.s3db nicht findet, wird eine leere Datenbank erzeugt, in der die Tabelle AusgHauptgruppe natürlich nicht existiert.



  • @Schlangenmensch

    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.s3db

    Daher 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 bei from 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 umgeschrieben

    void 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_BUSY

    Sagt 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 locked😉

    Jetzt wäre nur interessant, warum er nicht richtig abgeschlossen hat...

    Nachtrag:
    Habe folgendes direkt nach dem öffnen der db eingefügt

    sqlite3_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 und COMMIT TRANSACTION solltest du nicht brauchen. reset und finalize garantieren jeweils, das die implizierte Transaktion abgeschlossen wird. Mit sqlite3_prepare_v2 und finalize sollte auch das reset überflüssig sein 😉

    Aber auch finalize und reset 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!




Anmelden zum Antworten