SQLite error in QT - QSqlError("", "Parameter count mismatch", "") - sql

I'm trying to simply count the amount of records that has a 'true' status.
this is the SQLite table structure:
CREATE TABLE Suppliers(ID INTEGER PRIMARY KEY AUTOINCREMENT,Name varchar(50),Number varchar(15),URL varchar(70),Status bool,ShippingCost integer)
I am then calling a query from QT as follows:
int SQLiteController::ActiveSupplierCount()
{
int count = 0;
QSqlQuery Query;
Query.prepare("SELECT *"
"FROM Suppliers"
"WHERE Status = (:Status)");
Query.bindValue(":Status", true);
Query.exec();
qDebug() << Query.lastError();
while(Query.next() == true)
{
count++;
}
qDebug() << count;
return count;
};
The last error returned here is "Parameter count mismatch"
and I cannot figure out why... There is only 1 parameter, and I assign to that 1 parameter.

Try to add some extra spaces after each line of your query like this
Query.prepare("SELECT * "
"FROM Suppliers "
"WHERE Status = (:Status)");

Related

Sqlite Update query with SqliteModernCpp

I am using the SqliteModernCpp library. I have a data access object pattern, including the following function:
void movie_data_access_object::update_movie(movie to_update)
{
// connect to the database
sqlite::database db(this->connection_string);
// execute the query
std::string query = "UPDATE movies SET title = " + to_update.get_title() + " WHERE rowid = " + std::to_string(to_update.get_id());
db << query;
}
Essentially, I want to update the record in the database whose rowid (the PK) has the value that the object to_update has in its parameter (which is returned by get_id()).
This code yields an SQL logic error. What is the cause of this?
It turned out single quotes (') within the query string being created were missing. The line should be:
std::string query = "UPDATE movies SET title = '" + to_update.get_title() + "' WHERE rowid = " + std::to_string(to_update.get_id());
Since there is no UPDATE example in the official docs on github, This is how UPDATE queries should be implemented with prepared statements and binding
#define MODERN_SQLITE_STD_OPTIONAL_SUPPORT
#include "sqlite_modern_cpp.h"
struct Book {
int id;
string title;
string details;
Book(int id_, string title_, string details_):
id(std::move(id_)),
title(std::move(title_)),
details(std::move(details_)) {}
}
int main() {
Book book = Book(0, "foo", "bar")
sqlite::database db("stackoverflow.db");
// Assuming there is a record in table `book` that we want to `update`
db <<
" UPDATE book SET "
" title = ?, "
" details = ? "
" WHERE id = ?; "
<< book.title
<< book.details
<< book.id;
return 0;
}

How to delete specific row from sqlite database and bind with qlineedit?

I can delete specific rows using manual SQL query command. But can not delete from QLineEdit. How to bind with QLineEdit?
Here is my code:
person_name = ui->txt_UserName->text ();
mobile_number = ui->txt_Pass->text ();
//delete values
QString deleteStatement = "DELETE FROM phonebook_info WHERE user_name = ':person_name'";
query->bindValue (":person_name", person_name);
query->exec (deleteStatement);
if(query->exec ()){
QMessageBox::information (this, "Information!", "Row Deleted.", QMessageBox::Ok);
ui->statusBar->showMessage ("Row Deleted.");
} else {
QMessageBox::critical (this, "Information!", "Row not Deleted.", QMessageBox::Ok);
ui->statusBar->showMessage ("Row not Deleted.");
}
query executed but not delete. What am I doing wrong?
The syntax doesn't look right and you call query->exec() twice. This is how you should run the prepared statement:
QSqlQuery query = new QSqlQuery(databaseInstance);
bool ok = query->prepare(deleteStatement);
if (!ok) {
qWarning() << "SQL error:" << deleteStatement;
}
query->bindValue(":person_name", person_name);
query->exec();

Return a value from SQL Query Qt

I am trying to return a value from SQL Query. When logging in, 'Type' is a value in the database, 1,2 or 3. username and password are QStrings in the code.
In my attempt, this returns the wrong value (just a 1)
int userrole = roleQry.exec("SELECT Type FROM [tss_people] WHERE Username=\'" + username + "' AND Password='" + password + "'");
qDebug() << userrole;
QSqlQuery::exec() returns a status, i.e. whether the query was successfully executed or not.
Results can be optained by iterating over the query
while(roleQry.next()) {
qDebug() << roleQry.value(0).toInt();
}

SQLITE update query fails

I am trying to update the table column by appending with new data of QtSQl database. I need to update the column imgpath by appending with new data.
Below is the code, but it always fails, what could be the issue?.
QSqlQuery query(db);
query.exec("create table table1 (id integer primary key autoincrement, time varchar(20), imgpath varchar(20))");
query.exec("insert into table1 values(NULL,'00:15:25','img0.jpg')");
query.exec("insert into table1 values(NULL,'00:15:25','img1.jpg')");
bool up = query.exec("update table1 set imgpath=concat(';newImage.jpg',imgpath) where ID=1");
if(up==false)
qDebug()<<"Update failed";
Update:
Complete code:
QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");
db.setDatabaseName("./newDB");
db.open();
QSqlQuery query(db);
query.exec("create table table1 (id integer primary key autoincrement, time varchar(20), imgpath varchar(20))");
query.exec("insert into table1 values(NULL,'00:15:25','img0.jpg')");
query.exec("insert into table1 values(NULL,'00:15:25','img1.jpg')");
//bool up = query.exec("update table1 set imgpath='newimage.jpg',time='' where ID=1");
bool up = query.exec("update table1 set imgpath=concat(';newImage.jpg',imgpath)");
if(up==false){
qDebug()<<"Update failed";
qDebug() << db.lastError();
}
query.exec("SELECT * FROM table1 limit 100");
QVector<QStringList> lst;
while (query.next())
{
QSqlRecord record = query.record();
QStringList tmp;
for(int i=0; i < record.count(); i++)
{
tmp << record.value(i).toString();
}
lst.append(tmp);
}
foreach (const QStringList &var, lst) {
qDebug() << var;
}
SQLite doesn't support the concat function. If you remove
imgpath=concat(';newImage.jpg',imgpath)");
and replace it with standard colName='Value' syntax I'm betting that everything will start working. If you want to append text to the current value you should be able to do it with something like the following syntax:
bool up = query.exec("update table1 set imgpath=';newImage.jpg'||imgpath");

query.next() returning false

I have used the query.next() function inside my code, but its returning false.
I even checked in the database, there are 4 records present. But the code shows only one.
However if i use query.next() before the code of query.valid() then it doesn't show any record
Please help
qDebug() << "entering payment: get all the unchecked invoices for user: " + user;
QStringList tmp;
QSqlQuery query(m_storageUserManager->database());
m_storageUserManager->dumpTable(m_invoiceInfoTable);
m_storageUserManager->dumpTable(m_invoiceUserTable);
qDebug()<<"THE NAME OF THE INVOICE USER TABLE_----=-----------------"<<m_invoiceInfoTable;
qDebug()<<"THE NAME OF THE INVOICE USER TABLE_----=-----------------"<<m_invoiceUserTable;
query.prepare("SELECT invoice FROM "+ m_invoiceInfoTable +" WHERE invoice = (SELECT
invoice FROM "+ m_invoiceUserTable +" WHERE user=:user)");
// query.prepare("SELECT invoice FROM " + m_invoiceInfoTable + ","+ m_invoiceUserTable +" WHERE " + m_invoiceInfoTable + ".user = " + m_invoiceUserTable + ".:user");
query.bindValue(":user", user);
query.exec();
query.first();
qDebug()<<"Unchecked invoices done!!! " ;
if(query.isValid()) {
do {
tmp.append(query.value(0).toString()); //as the value returned by value() is a QVariant so we need to change it to String.
} while(query.next());
} else
tmp.append("No Unchecked invoice in the database");
return tmp;
To check if the query was successful you should test the return value of either QSqlQuery::exec() or QSqlQuery::isActive() before trying to call first/next/last (when you pass the query string to the constructor of QSqlQuery, the query is already executed, so, you need to use QSqlQuery::isActive()).
first(), next() and last() return true if they positioned the query on a valid record, you don't have to test isValid() separately. Since first() is a positioning function too, you can read the value without calling next() directly after, unless you want to skip the first record.
Since you may want to add fields from the the "invoice-info" table to your query, I kept the subquery (with IN instead of = as Mat already answered in the comment).
query.prepare(QString("SELECT invoice FROM %1 WHERE invoice "
"IN (SELECT invoice FROM %2 WHERE user=:user)")
.arg(m_invoiceInfoTable, m_invoiceUserTable));
/*
// Or with an inner join
query.prepare(QString("SELECT %1.invoice FROM %1 "
"INNER JOIN %2 ON %1.invoice = %2.invoice "
"WHERE user=:user").arg(m_invoiceInfoTable, m_invoiceUserTable));*/
query.bindValue(":user", user);
if (!query.exec()) {
tmp.append("Query error: %1" + query.lastError().text());
} else if (!query.first()) {
tmp.append("No Unchecked invoice in the database");
} else {
do {
tmp.append(query.value(0).toString());
} while(query.next());
}
Try
query.prepare("SELECT invoice FROM " + m_invoiceInfoTable + " WHERE user=:user");