i have a problem with my SQLite Database in QT5. I have table called "mytable" and im trying to save, change or load data there. The table looks like this (CODE):
"mytable" ("id" INTEGER PRIMARY KEY NOT NULL , "name" VARCHAR NOT NULL , "akcie" INTEGER NOT NULL )
Then im trying to work with this database like this (CODE):
void MainWindow::on_pushButton_save_clicked()
{
QString jmeno, IDcko, ak;
IDcko = ui->lineEdit_ID->text();
jmeno = ui->lineEdit_Name->text();
ak = ui->lineEdit_Akcie->text();
open_connection();
QSqlQuery query;
query.prepare("INSERT INTO mytable(id, name, akcie) VALUES(id= \'"+ IDcko +"\', name= \'"+ jmeno +"\', akcie= \'"+ ak +"\')");
if(query.exec())
{
QMessageBox::information(this, tr("SAVED"), tr("Some text."));
close_connection();
}
else
{
QMessageBox::critical(this, tr("NOT SAVED"), query.lastError().text());
qDebug() << query.lastError().text();
}
}
In the same file im opening connection like this (CODE):
bool MainWindow::open_connection()
{
QSqlDatabase database;
database = QSqlDatabase::addDatabase("QSQLITE");
database.setDatabaseName("..\\added\\test_table.sqlite");
if(!database.open())
{
qDebug() << "not opened connection";
return false;
}
else
{
qDebug() << "opened connection";
return true;
}
}
And im still getting error: "No query Unable to fetch row", i have been looking for the answer really hard but nothing worked. Could it be because of some includes or am I doing something wrong?
Thank you in advance for your help!
You are not preparing the query right. Use bindings like:
query.prepare("INSERT INTO mytable(id, name, akcie) VALUES(:id, :name, :akcie)");
query.bindValue(":id", IDcko);
query.bindValue(":name", jmeno);
query.bindValue(":akcie", ak);
You did not execute the query. You should use bindings like:
query.prepare("INSERT INTO mytable(id, name, akcie) VALUES(?, ?, ?)");
query.addBindValue(IDcko);
query.addBindValue(jmeno);
query.addBindValue(ak);
query.exec();
or, like #Miki mentioned, with the help of query.bindValue(":id", IDCko) function.
The last way will be to write the query text straightly (without the need to separately call query.exec():
query("INSERT INTO mytable(id, name, akcie) VALUES(id= \'"+ IDcko +"\', name= \'"+ jmeno +"\', akcie= \'"+ ak +"\')");
Related
I am making a library management software using Qt and Sqlite3.
constructor:
db = QSqlDatabase :: addDatabase("QSQLITE");
model = new QSqlTableModel(this, db);
db.setDatabaseName(":/lib/libre coupe.db");
db.setHostName("Libre Coupe");
if(db.open())
{
QSqlQuery query(db);
if (! query.exec("CREATE TABLE IF NOT EXISTS books (NAME VARCHAR(100) NOT NULL, AUTHOR VARCHAR(100) NOT NULL, UID VARCHAR(100) NOT NULL) "))
{
QMessageBox::information(this, "title", "Unable to use Sqlite");
}
if(query.lastError().text() != " ")
QMessageBox::critical(this, "Oops", query.lastError().text());
model->setTable("books");
model->select();
model->setHeaderData(0, Qt::Horizontal, tr("Name") );
model->setHeaderData(1, Qt::Horizontal, tr("Author") );
model->setHeaderData(2, Qt::Horizontal, tr("Uid") );
model->setEditStrategy(QSqlTableModel::OnManualSubmit);
if(!query.exec("SELECT * FROM books;"))
QMessageBox::critical(this, "Oops", query.lastError().text());
int i = 0;
while(query.next())
{
model->setData(model->index(i, 0), query.value(query.record().indexOf("NAME")));
model->setData(model->index(i, 1), query.value(query.record().indexOf("AUTHOR")));
model->setData(model->index(i, 2), query.value(query.record().indexOf("UID")));
++i;
}
}
else
QMessageBox::critical(this, "Oops!", "Could not open the database");\
I faced a problem that the database was not created automatically. So, i created it manually and added it to my resource so that it exists on every computer which uses my application.
I ran my app and went to the directory containing "libre coupe.db". There using the terminal, i found out that no table was created. I see no error message. My other functions like save don't work too while the same commands typed directly into Sqlite using terminal works as expected.
I even used the debugger and found that the program does enter the if condition i.e. the database opens successfully.
I used the following command to check if the table existed:
sqlite3 "libre coupe.db"
.tables
First line:
db.setDatabaseName(":/lib/libre coupe.db");
the starting ":" means you are trying to access an embedded binary resource using Qt's resource system.
However, SQLite databases cannot be stored in the Qt resource system. If your database is instead located at /lib/libre coupe.db, you should remove the colon at the beginning.
I'm trying to get the row count of a QSqlQuery, the database driver is qsqlite
bool Database::runSQL(QSqlQueryModel *model, const QString & q)
{
Q_ASSERT (model);
model->setQuery(QSqlQuery(q, my_db));
rowCount = model->query().size();
return my_db.lastError().isValid();
}
The query here is a select query, but I still get -1;
If I use model->rowCount() I get only ones that got displayed, e.g 256, but select count(*) returns 120k results.
What's wrong about it?
This row count code extract works for SQLite3 based tables as well as handles the "fetchMore" issue associated with certain SQLite versions.
QSqlQuery query( m_database );
query.prepare( QString( "SELECT * FROM MyDatabaseTable WHERE SampleNumber = ?;"));
query.addBindValue( _sample_number );
bool table_ok = query.exec();
if ( !table_ok )
{
DATABASETHREAD_REPORT_ERROR( "Error from MyDataBaseTable", query.lastError() );
}
else
{
// only way to get a row count, size function does not work for SQLite3
query.last();
int row_count = query.at() + 1;
qDebug() << "getNoteCounts = " << row_count;
}
The documentation says:
Returns ... -1 if the size cannot be determined or if the database does not support reporting information about query sizes.
SQLite indeed does not support this.
Please note that caching 120k records is not very efficient (nobody will look at all those); you should somehow filter them to get the result down to a manageable size.
I'm using FMDatabase to operate on an sqlite3 database. Here's my code:
NSString *dbFilePath = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0] stringByAppendingPathComponent:[NSString stringWithFormat:#"temp_info.db"]];
FMDatabase *fmdb = [FMDatabase databaseWithPath:dbFilePath];
if (![fmdb open]) {
NSLog(#"......");
} else {
NSString *sql = #"CREATE TABLE IF NOT EXISTS test1(id INTEGER, name TEXT, create_time TEXT)";
if (![fmdb executeUpdate:sql]) {
NSLog(#"......");
}
for (int i = 0; i < 3; i++) {
BOOL result = [fmdb executeUpdate:#"INSERT INTO test1(id, name, create_time) values(?,?,?)", i+1, #"test", #"12-09-10 12:10"];
NSLog(#"%d", result);
}
// EXC_BAD_ACCESS
}
When I run the line:
BOOL result = [fmdb executeUpdate:#"INSERT INTO test1(id, name, create_time) values(?,?,?)", i+1, #"test", #"12-09-10 12:10"];
I get an EXC_BAD_ACCESS error. Why?
question has been solved!
*1.*All arguments provided to the -executeUpdate: method(or any of the variants that accept a va_list as a parameter) must be objects.The following will be not work (and will result in a crash):
[db executeUpdate:#"INSERT INTO mytable VALUES (?)", 66];
The proper way to insert a number is to box it in an NSNumber object:
[db executeUpdate:#"INSERT INTO mytable VALUES (?)", [NSNumber numberWithInt:66]];
*2.*Alternatively,you can use the -execute*WithFormat: variant to use NSString-style substitution:
[db executeUpdateWithFormat:#"INSERT INTO mytable VALUES (%d)", 66];
Internally,the -execute*WithFormat: methods are properly boxing things for you.The following percent modifiers are recognized:%#,%c,%s,%d,%D,%i,%u,%U,%hi,%hu,%qi,%qu,%f,%ld,%lu,%lld,and %llu.Using a modifier other than those will have unpredictable results.If,for some reason,you need the % character to appear in your SQL statement,you should use %%.
I have saved an image in sqlite and i am trying to retrieve it and displaying it in a QLabel using this code.
connect(ui.tableView->selectionModel(), SIGNAL(currentRowChanged(QModelIndex,QModelIndex)),
this, SLOT(getImage(QModelIndex,QModelIndex)));
void smith::getImage()
{
.......
QModelIndex index = ui.tableView->currentIndex();
QString sqlQuery = QString("SELECT image FROM %1 WHERE id=:id").arg(tableName);
query.prepare(sqlQuery);
QSqlRecord recordz = tableModel->record(index.row());
query.bindValue(":id", recordz.value("id").toInt());
query.exec();
tableModel->select();
QByteArray array = query.value(0).toByteArray();
QBuffer buffer(&array);
buffer.open( QIODevice::ReadOnly );
QImageReader reader(&buffer, "PNG");
QImage image = reader.read();
if( image.isNull() )
{
QMessageBox::about(this, tr("Image Is Null"),
tr("<h2>Image Error</h2>"
"<p>Copyright © 2011."
"<p>Message Box To Check For "
" Errors "
));
}
ui.imageLabel->setPixmap( QPixmap::fromImage(image));
}
The project compiles without any errors but the image won't show.
I'd suggest adding some error-checking to your code, to narrow down where the error occurs.
For example, the documentation for QImageReader::read() says that if the image can't be read, the resultant image is null, and it tells you how to find out what the error was.
So after your call to reader.read(), check image.isNull().
And earlier on, check array.size() to make sure that you really got a value back from the database.
And the check the result returned by buffer.open( QIODevice::ReadOnly ) - the docs say it will return false if the call failed.
I decided to test sqlite db for my Qt application.
I have created the sqlite db file with the proper statements (create table etc. and Inserted some rows of data).
My problem is that when I execute a select statement I don't get any records.
This is the code I use:
qq.sprintf("SELECT * from descriptors WHERE descriptors.id=%d ",idx);
query.exec(qq);
if( query.isSelect() ){
while (query.next()){
int fff = query.value(0).toInt();
}}
The problem is that I never get inside the while loop. query.next() doesn't seem to work.
any hints?
thanks in advance,
Thodoris
p.s. I forgot to write my configuration so: Qt 4.7.3, windows 7, visual studio 2008
Other than the mistake hexa posted, query.isSelect() will always return true even if the query failed. You need to check the result of exec():
QSqlQuery query;
query.prepare( "SELECT * FROM descriptors WHERE id = ?" );
query.bindValue( 0, idx ); // assuming idx is an integer/long/QVariant value
if( !query.exec() )
{
// Error Handling, check query.lastError(), probably return
}
// Note: if you don't return in case of an error, put this into the else{} part
while( query.next() )
{
int fff = query.value( 0 ).toInt();
}
In my case, backward iteration over QSqlQueries worked. I think this could be a bug somewhere in the QSQLite Driver implementation.
QSqlQuery q = db.exec("SELECT * FROM Table");
if (q.last()) {
do {
// Do something with row...
} while (q.previous());
}