_SQLite_Exec - Limit für Befehlslänge?

  • Ich stelle zum Befüllen der Tabellen einer SQLite-DB die Queries in einer Funktion zusammen. Dabei hänge ich alle Insert-Befehle hintereinander und führe danach aus:

    Tabelle 1 hat nur ein paar Hundert Datensätze, das Insert funktioniert ohne Probleme.

    Für Tabelle 2 stelle ich 1,8 Mio Datensätze zusammen. AutoIt hat kein Problem mit der Stringlänge.

    Aber das _SQLite_Exec schlägt fehl, Fehlercode = 1 - Error calling SQLite API 'sqlite3_exec'. Natürlich sehr aussagekräftig. :whistling:

    Meine Vermutung ist, dass der Befehlsstring einfach zu lang ist (~103 Mio. Zeichen).

    Bevor ich jetzt anfange zu stückeln: Ist euch ein Limit für den Befehlsstring bekannt? Ich möchte mich da nicht rantasten.

  • Ist euch ein Limit für den Befehlsstring bekannt?

    Hi BugFix :

    (ein reiner Schuss ins Blaue ;) )

    Bei https://www.sqlite.org/limits.html findet man folgende Aussage :

    Zitat

    1. Maximum length of a string or BLOB :

    The maximum number of bytes in a string or BLOB in SQLite is defined by the preprocessor macro SQLITE_MAX_LENGTH. The default value of this macro is 1 billion (1 thousand million or 1,000,000,000). You can raise or lower this value at compile-time using a command-line option like this:

    -DSQLITE_MAX_LENGTH=123456789

    The current implementation will only support a string or BLOB length up to 231-1 or 2147483647.

    (... aber das hast Du wahrscheinlich bereits selbst gefunden)

    86598-musashi-c64-png

    "Am Anfang wurde das Universum erschaffen. Das machte viele Leute sehr wütend und wurde allenthalben als Schritt in die falsche Richtung angesehen."

  • Meines Wissens nach müssen nicht alle Inserts in ein _SQLite_Exec um in eine Transaktion ("BEGIN;...COMMIT;") zu kommen.

    Du solltest also einfach

    AutoIt
    _SQLite_Exec($hSQL, 'BEGIN TRANSACTION;')
    For $i=0 to 10 Step 1
        _SQLite_Exec($hSQL, StringFormat("INSERT INTO tab1 VALUES (%d, '%s', '%s', '%s', '%s', '%s', '%s');", $i, _
                             $aSplit[0], $aSplit[1], $aSplit[2], $aSplit[3], $aSplit[4], $aSplit[5]))
    Next
    _SQLite_Exec($hSQL, 'COMMIT;')

    aufrufen können.

    Ansonsten halt in mehrere Transaktionen aufteilen.

    Ich weiß nicht, ob die dann trotzdem als ein command gelten, oder nacheinander ausgeführt werden und nur für ein mögliches rollback relevant sind.

    Ansonsten dürfte das hier relevant sein:

    Die länge einer einzelnen insert value (die Musashi erwähnte) dürfte dabei nicht so relevant sein.

  • Moin,

    wenn Du mit Fehlercode = 1 meinst, dass @error = 1 ist, kann der Fehler aus

    AutoIt
        If @error Then Return SetError(1, @error, $SQLITE_MISUSE) ; DllCall error

    in _SQLite_Exec() stammen. Dann müsste $SQLiteResult den Wert 21 enthalten und in @extended sollte der ursprünglich vom DllCall gesetzte Fehler zu finden sein. Hast Du das mal geprüft?

    Bei von SQLite gelieferten Fehlern sollte @error auf -1 gesetzt sein und eine Fehlermeldung per ConsoleWrite() erstellt werden, wenn das Skript nicht compiliert ist,

  • Hallo Bugfix!

    Ich kann dir nur empfehlen, dass du nach Hausnummer 200000 einen Insert machst.

    Ich importiere DNS Logfiles in eine SQLite Datenbank und dort bekomme ich einen Speicherfehler da der Insertstring zu groß wird.

    Um diesen zu umgehen habe ich dann eben nach 200K einen insert gemacht und die Insertstring Variable "gelöscht".

    Auf dein Beispiel angewendet. (Ist jetzt nicht wirklich getestet aber du verstehst sicher was ich damit meine)

    Begin Transaction;

    Insertstring

    Commit Transaction;

    Ist meiner Erfahrung nach die schnellste Methode eines Datenimports.

    If not :?: then ?( else :thumbup:

  • Ist meiner Erfahrung nach die schnellste Methode eines Datenimports.

    Die meiner Erfahrung nach schnellste Methode eines Datenimportes in sqlite ist die >>.import-Funktion<< des CLI-Tools von sqlite.

    Man benötigt also noch die Datei >>sqlite3.exe<< in irgendeinem erreichbaren Pfad (z.b. das Skriptverzeichnis).
    Dann kann man das Tool von AutoIt aus über die Funktion >>_SQLite_SQLiteExe()<< verwenden.

    Der Ablauf wäre dann folgender: Aus den Daten, welche man importieren möchte eine csv/tsv erstellen (fix in einem Loop erledigt).
    Und dann den Import durch die sqlite3.exe erledigen lassen.
    Auf die Art umgeht man den Bau des SQL-Strings und braucht sich um dessen Größenbeschränkungen auch nicht mehr zu sorgen.

    Der prinzipielle Aufbau ist hierbei recht simpel:

    Einmal editiert, zuletzt von AspirinJunkie (21. November 2023 um 11:18)