Prepared Statements und CREATE TABLE



  • Kann es sein, dass Prepared Statements beim erstellen von Tabellen nicht funktionieren?

    Ich möchte in einem Programm die Möglichkeit anbieten, selber Tabellen zu erstellen mit eigenen Spalten. Dazu wollte ich dann später einen SQl Query bauen.

    Dazu muss ich aber erstmal eine Tabelle mit variablen Namen erstellen können. Hab zu Testzwecken folgenden Code.

    QSqlDatabase db = QSqlDatabase::database("sqlite");
        if (!db.open())
        {
            QErrorMessage errMsg;
            errMsg.showMessage("Fehler beim verbinden zur Datenbank");
            errMsg.exec();
        }
    
        QString sql =   "CREATE TABLE :table ("
                        "ID INT PRIMARY KEY      NOT NULL,"
                        "CREATEDAT TEXT                 NOT NULL,"
                        "UPDATEDAT TEXT                 NOT NULL);";
    
        QSqlQuery query(db);
    
        query.prepare(sql);
        query.bindValue(":table", ui->lineEdit_tableName->text());
        query.exec();
        qDebug() << query.lastError();
    
        db.close();
    

    Ich habe schon alle unterschiedlichen Prepared Statements durchprobiert, aber bekomme immer die Meldung

    QSqlError("", "Parameter count mismatch", "")

    Ich könnte natürlich auch ohne Prepared Statements arbeiten, aber das ist unsicher. Der String könnte dann so aussehen.

    QString sql =   "CREATE TABLE " + ui->lineEdit_tableName->text() + "("
                        "ID INT PRIMARY KEY      NOT NULL,"
                        "CREATEDAT TEXT                 NOT NULL,"
                        "UPDATEDAT TEXT                 NOT NULL);";
    

    Unter Php gibt es ja sowas wie htmlspecialchars(), aber sowas habe ich bisher nicht gefunden.



  • Das Prepared Statements sollte grundsätzlich schon für CREATE TABLE gehen.
    Nur kannst du normalerweise keine Tabellennamen an Parameter binden.
    Nicht in CREATE TABLE aber genau so wenig in SELECT.

    Probier testweise mal "SELECT * FROM :table" aus, das geht üblicherweise auch nicht.

    Spaltennamen-Parameter gehen übrigens auch nicht. Und die Konstante für ein "SELECT TOP ..." auch nicht. (Und vermutlich noch viele weitere denkbare Anwendungsfälle.)

    Sind halt so die Einschränkungen von Prepared Statements.

    Wenn man darüber nachdenkt was Prepared Statements eigentlich darstellen, nämlich vorcompilierte "SQL Programme" mit Parametern, wird auch klar wieso das alles nicht geht.
    Ist quasi das selbe wie dass du in C++ keine String-Parameter verwenden kannst um per Variablenname auf Variablen zuzugreifen.



  • ps:

    Bennisen schrieb:

    Unter Php gibt es ja sowas wie htmlspecialchars(), aber sowas habe ich bisher nicht gefunden.

    Äh.
    ' duch '' ersetzen? Ist jetzt nicht wirklich so schwer.



  • hustbaer schrieb:

    ps:

    Bennisen schrieb:

    Unter Php gibt es ja sowas wie htmlspecialchars(), aber sowas habe ich bisher nicht gefunden.

    Äh.
    ' duch '' ersetzen? Ist jetzt nicht wirklich so schwer.

    Bitte was? Verstehe gerade nicht was du meinst. Meinst du den Tabellennamen im Query mit zwei ' Zeichen umklammern?



  • Er. Unfug, ich war bei String-Literals 🙂

    Du hast ja nen Tabellennamen, den muss man in "" oder [] setzen, nicht in ''.
    Also entweder

    Tabellenname mit Spaces und Anfürhungszeichen --> " <-- hier
    =>
    "Tabellenname mit Spaces und Anfürhungszeichen --> "" <-- hier"

    Oder

    Tabellenname mit Spaces und eckiger Klammer --> ] <-- hier
    =>
    [Tabellenname mit Spaces und eckiger Klammer --> ]] <-- hier]

    Die Regel beim Escapen von SQL Literals ist auf jeden Fall immer trivial: einfach das "hier ist Ende" Zeichen verdoppeln.



  • Sagt mir garnichts. Noch nie von gehört. Hab auf jedenfall jetzt mit regulären Ausdrücken gearbeitet um bei der Wahl der Namen schonmal ein paar Fehler aus zu schließen.



  • Quote einfach den Tabellennamen mit ", und ersetze davor alle " im Tabellennamen mit "".
    Also eben
    komischer " name
    =>
    "komischer "" name"

    Dann brauchst du keine fehleranfällige Validierung mit Regexen, weil die SQL Engine dann alles zwischen den beiden einzelnen " als Teil des Tabellennamens interpretiert. Und wenn da Zeichen enthalten sein sollten die die SQL Engine nicht als Teil von Tabellennamen erlaubt, dann bekommst du einen entsprechenden Fehler von der SQL Engine gemeldet. Sie wird auf jeden Fall *nicht* anfangen den Tabellennamen irgendwie weiter als SQL Code zu interpretieren.

    Bennisen schrieb:

    Sagt mir garnichts. Noch nie von gehört.

    Kann ich ja nix dafür wenn du dich nicht ausreichend mit SQL auskennst. Nur... deswegen sag ich es dir ja. Du sollst mir das auch nicht einfach glauben, verlangt keiner, würde ich auch nicht einfach so. Du solltest es aber vielleicht mal googeln und deine Kenntnisse erweitern, anstatt mit den bestehenden Kenntnissen irgendwie rumzuwursteln. Suchstring "how to escape sql identifier names" oder sowas (ohne die "" natürlich).



  • werde ich mir mal anschauen. danke


Anmelden zum Antworten