Sqlite Variablen in Datenbank einfügen



  • Guten Abend.
    Ich habe hier folgende Sql Anweisung

    UPDATE book
    SET name = newName
    WHERE id = 1
    

    newName soll dabei eine Variable sein. Allerdings funktioniert das ja leider nicht, da name nun “newName“ zugewiesen wird, anstatt dem Wert welcher in newName gespeichert ist.
    Ich hoffe mir kann jemand helfen, eine Lösung zu finden, um den Wert zu nehmen.

    Schönen Abend noch 😉
    MfG ENDER



  • @ENDER sagte in Sqlite Variablen in Datenbank einfügen:

    newName

    Probier's mal mit $newName oder @newName. Falls das nicht geht kannst du vermutlich nur noch die "indizierten" Platzhalter verwenden, also ?.



  • @hustbaer also mit & und $ hat es leider nicht funktioniert. Was meinst du denn mit indizierten platzhaltern mit dem ?



  • @ENDER ups das eine war ein @, mit dem hat es leider auch nicht funktioniert



  • Es gibt manche Datenbank-Treiber die nur ? als Platzhalter unterstützen. Wenn man mehrere Parameter braucht kann man also keine Namen vergeben, sondern nur Indexe (0, 1, 2, ...).

    Aber zeig mal deine Code her mit dem du das Statement ausführst. Vielleicht wird dann klar was das Problem ist.



  • @hustbaer

    #include <iostream>
    #include <sqlite3.h>
    #include <stdio.h>
    #include <stdlib.h>
    
    static int callback (void* data, int argc, char** argv, char** azColName) {
        int i;
        fprintf (stderr, "%s: ", (const char*)data);
    
        for (i = 0; i < argc; i++) {
            printf ("%s = %s\n", azColName[i], argv[i] ? argv[i] : "NULL");
        }
        printf ("\n");
        return 0;
    }
    
    int main (int argc, char* argv[]) {
    
        sqlite3* db;
        char* zErrMsg = 0;
        int rc;
        char* sql;
        const char* data = "Callback function called";
    
        /* Open database */
        rc = sqlite3_open ("test.db", &db);
    
        if (rc) {
            fprintf (stderr, "Can't open database: %s\n", sqlite3_errmsg (db));
            return (0);
        }
        else {
            fprintf (stderr, "Opened database successfully\n");
        }
        std::string newName;
        std::cin >> newName;
        /* Create merged SQL statement */
        sql = "UPDATE COMPANY SET NAME = newName WHERE ID = 1";
        "SELECT * from COMPANY";
    
        /* Execute SQL statement */
        rc = sqlite3_exec (db, sql, callback, (void*)data, &zErrMsg);
    
        if (rc != SQLITE_OK) {
            fprintf (stderr, "SQL error: %s\n", zErrMsg);
            sqlite3_free (zErrMsg);
        }
        else {
            fprintf (stdout, "Operation done successfully\n");
        }
        sqlite3_close (db);
        return 0;
    }
    

    Also hier ist mein Code. Meine Datenbank hat die Felder ID, NAME, AGE, ADDRESS und SALLARY
    newName wird durch den User eingegeben, und ich möchte dass das dann an der Stelle in meiner Sqlite Datenbank geupdatet wird



  • Wenn du Zeichenketten einfügen möchtest gibt´s zwei Möglichkeiten:

    1. Du musst den Wert in einzelne Hochkommata einfassen, z.B.
    UPDATE company SET name = 'ACME Labs' WHERE id = 1
    
    1. Du verwendest Prepared Statements und bindest den Wert an einen Parameter, das ist vermutlich auch das, was hustbaer meinte.

    Option 2) ist das Mittel der Wahl, da es SQL Injections verhindert. Du solltest dich also mal schlau machen, wie man mit SQLite Prepared Statements verwendet. Ein C++ Wrapper macht die Sache vielleicht einfacher, aber selbst ohne sind Prepared Statements ziemlich einfach zu benutzen.



  • @ENDER du musst prepare und bind verwenden.
    https://www.sqlite.org/c3ref/bind_blob.html



  • @DocShoe Also das mit den Hochkammata habe ich nicht gemeint, aber prepared statments ist glaube ich das richtige



  • @ENDER Ich glaube dass es auch erstmal wichtig ist zu verstehen wieso das so wie du es versucht hast schonmal grundsätzlich nicht gehen kann. Die SQLite Library kann nämlich die Variable newName nicht kennen - weder ihren Namen noch ihren Inhalt. D.h. ohne etwas was du explizit aufrufst, mit der du der Library diese Variable sozusagen "bekannt machst", kann es einfach nicht gehen.

    Und wie du es lösen kannst wurde ja bereits geschrieben.



  • @hustbaer Vielen dank, das habe ich jetzt verstanden. Ich habe erst vorgestern angefangen mich mit Sqlite zu beschäftigen und ich muss sagen, dass es für den Anfang echt verwirrend ist. Aber jetzt geht es langsam



  • @ENDER sagte in Sqlite Variablen in Datenbank einfügen:

    @hustbaer Vielen dank, das habe ich jetzt verstanden. Ich habe erst vorgestern angefangen mich mit Sqlite zu beschäftigen und ich muss sagen, dass es für den Anfang echt verwirrend ist. Aber jetzt geht es langsam

    Nur als Hinweis: das hat nichts mit SQLite zu tun, sondern gilt generell für alle Datenbanken. Lies dir mal https://de.wikipedia.org/wiki/SQL-Injection durch.



  • @wob @ENDER
    Das was ich meine hat generell mit C bzw. C++ zu tun. Vielleicht hilft ein Beispiel:

    void myFunction() {
        int myVariable = 42;
        someOtherFunction("PRINT $myVariable");
    }
    

    @wob ich weiss dass du das folgende weisst, ich tagge dich nur weil hier anscheinend ein Misverständnis besteht darüber was ich gemeint hatte.

    Disclaimer: ich beziehe mich hier auf Standardmittel, also auf das was der C bzw. C++ Standard garantiert. Wenn man wild zu tricksen anfängt, nonstandard Mittel verwendet und ein wenig IB/UB riskiert, dann geht sowas vermutlich schon -- aber auch nur unter ganz bestimmten Bedingungen die ziemlich realitätsfremd sind (z.B. kompilieren ohne Optimierungen + mit ausliefern des .PDB/.DBG Files + Einsatz von Reverse-Engineering Libraries).


    Im gezeigten Code ist es völlig unmöglich dass someOtherFunction irgendwie Kenntnis von/Zugriff auf myVariable hat. Es kann also auch unmöglich funktionieren dass someOtherFunction hier irgendwie den Wert von myVariable ausgibt. Um das sagen zu können muss man someOtherFunction nicht kennen und nichtmal wissen in welcher Sprache someOtherFunction implementiert ist. Es reicht dass man weiss das der gezeigte Code C oder C++ ist.

    Einmal weil man in C bzw. C++ einfach keine Variablen per Name irgendwie ausfindig machen kann. Und dann auch noch weil du als C bzw. C++ Funktion keinen Zugriff auf den Scope hast in dem du aufgerufen worden bist -- und myVariable schliesslich in diesem Scope lebt.

    Damit das gezeigte Beispiel wie gedacht funktionieren kann mus man also der anderen Funktion irgendwie sagen dass es hier eine Variable namens myVariable gibt und was deren Inhalt ist (bzw. es wäre auch möglich statt dessen Typ + Adresse bekannt zu machen, aber das vergessen wir mal).

    Das kann z.B. so aussehen:

    void myFunction() {
        int myVariable = 42;
    
        SomeObject obj;
        obj.defineVariable("myVariable", myVariable);
        obj.someOtherFunction("PRINT $myVariable");
    }
    

    Natürlich kann man das mit etwas Makro-Schweinerei auf sowas zusammendampfen:

    void myFunction() {
        int myVariable = 42;
        SOME_MACRO("PRINT $myVariable", myVariable);
    }
    

    Ohne die Erwähnung von myVariable beim Aufruf wird es aber nie und nimmer funktionieren können.



  • Dafür existiert der 1.Parameter in callback und der 4. in sqlite3_exec.



  • @Wutz Es geht hier um Query-Parameter.



  • Dazu sind - wie oben erwähnt - Bindingvariablen da, mit dem entsprechenden API Funktionen.



  • Ist mir schon klar. Ich verstehe bloss deinen Beitrag

    @Wutz sagte in Sqlite Variablen in Datenbank einfügen:

    Dafür existiert der 1.Parameter in callback und der 4. in sqlite3_exec.

    nicht. Weil der nichts mit dem hier Diskutierten zu tun hat.


Anmelden zum Antworten