7

I'm doing a simple parameterized query with Qt 5.3.1 (64-bit) on Windows 7 using the SQLite driver. When I use bindValue() to set the value of the single parameter of my query, I systematically get the dreaded "Parameter count mismatch" error. Everything works fine when I use addBindValue(). Note that the code with bindValue() works fine with Qt 4.8.5 (64-bit).

Here is the full code (main.cpp):

#include <QtSql>

int main(int, char* [])
{
    auto db = QSqlDatabase::addDatabase("QSQLITE");
    db.setDatabaseName("db.sqlite");
    db.open();

    {
        QSqlQuery query("CREATE TABLE IF NOT EXISTS hashes (filepath TEXT, modified INTEGER, hash TEXT)", db);
        query.exec();
    }

    QSqlQuery query("SELECT modified FROM hashes WHERE filepath = :fp", db);
    query.bindValue(":fp", "test.jpg");

    if (!query.exec())
        qDebug() << query.lastError();

    db.close();

    return 0;
}

QtCreator project file (qtsqltest.pro):

QT += core sql
TARGET = qtsqltest
TEMPLATE = app
SOURCES += main.cpp

Program output on my machine:

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

Any idea?

François Beaune
  • 4,270
  • 7
  • 41
  • 65
  • possible duplicate of [Qt QSqlQuery bindValue works with ? but not with :placeholders](http://stackoverflow.com/questions/20786003/qt-qsqlquery-bindvalue-works-with-but-not-with-placeholders) – László Papp Jul 11 '14 at 15:04

2 Answers2

7

I just found out that my question is a duplicate of this one and that the corresponding answer is correct.

It turns out that query strings passed to the constructor of QSqlQuery are executed immediately, as per the documentation.

It isn't clear why such queries are working fine with Qt 4.8.5, or why they do work with Qt 5.3.1 when using positional parameters (using ? placeholders) while they fail with named parameters (using : placeholders).

Community
  • 1
  • 1
François Beaune
  • 4,270
  • 7
  • 41
  • 65
  • 3
    I had a similar problem, but in my case what solved it was adding parenthesis in the query, so instead of `query.prepare( "INSERT INTO tablename (columnname) VALUES :placeholder" );` I had to do `query.prepare( "INSERT INTO tablename (columnname) VALUES (:placeholder)" );` – waldyrious Nov 16 '15 at 18:00
  • 3
    I had a similar problem (with a correct use of prepare), but mine mistake was a typo in sql query (I had "SELECT a, b, cFROM table" instead of "SELECT a, b, c FROM table")...Error message "Parameter count mismatch" was really misleading here...Might help someone, good luck! – vlp Feb 22 '18 at 19:34
  • I also had similar problem . But I was wrong at set datadase path > db.setDatabaseName(path); – Masthan Nov 22 '18 at 15:56
5

I don't have the reputation to add a comment to the solution, so here, just to add yet another potential culprit: I was trying to bind a value to the column name and I got the Parameter count mismatch error, which seems to be the go-to error message no matter what the actual error is :)

It turns out this is simply an invalid approach to SQL, see QSqlQuery with prepare and bindValue for column name Sqlite.

So instead of

query.prepare("UPDATE connections SET (:columnName) = (:value) WHERE id = (:id)");
query.bindValue(":columnName", someColumnName);
query.bindValue(":value", someValue);
query.bindValue(":id", someId);

do this:

query.prepare(QString("UPDATE connections SET %1 = (:value) WHERE id = (:id)").arg(someColumnName));
query.bindValue(":value", someValue);
query.bindValue(":id", someId);
// etc.

This is not what the OP did but this thread is what came first during my search and it might save somebody else some time.

Graprar
  • 51
  • 1
  • 1