结论:
只有使用Qt内置的默认连接名的时候,QSqlQuery才可以用空的构造函数,即如下是一一对应的:
mdb = QSqlDatabase::addDatabase("QSQLITE");
// 等价于 q(mdb)
QSqlQuery q;
q.exec("select *...");又或者指定了连接名,必须要按如下配对:
mdb = QSqlDatabase::addDatabase("QSQLITE","MyConnectName");
// 不能用空构造函数,提示 database not open
QSqlQuery q(mdb);
q.exec("select *...");结论对于子类化QSqlTableModel这样的模型同样有效,
如下是测试工程:
h:
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QSqlDatabase>
#include <QSqlTableModel>
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE
class MyModel : public QSqlTableModel{
Q_OBJECT
public:
explicit MyModel(QObject *parent = nullptr, QSqlDatabase db = QSqlDatabase());
void openQuery();
};
class MainWindow : public QMainWindow{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
private:
Ui::MainWindow *ui;
QSqlDatabase mdb;
MyModel *mmm;
protected:
private slots:
void on_pushButton_clicked();
};
#endif // MAINWINDOW_HCPP:
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "utility.h"
#include <QDebug>
#include <QKeyEvent>
#include <QMessageBox>
#include <QSqlQuery>
#include <QSqlError>
#include <QString>
#ifdef _MSC_VER
#pragma execution_character_set("utf-8")
#endif
// 分别选择一个,编译并运行
#define CONN_NAME "connectionName"
//#define CONN_NAME
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
if(QSqlDatabase::contains(CONN_NAME)){
T_INF <<"已经包含此连接名了:" << QString(CONN_NAME);
mdb = QSqlDatabase::database(CONN_NAME);
}
else{
QString conn = QString(CONN_NAME);
if(conn.isEmpty()){
T_INF << "使用默认NULL连接名";
mdb = QSqlDatabase::addDatabase("QSQLITE");
}
else{
T_INF << "使用自定义连接名:"<<conn;
mdb = QSqlDatabase::addDatabase("QSQLITE",conn);
}
mdb.setDatabaseName("fileName.sqllite");
}
if (!mdb.open()) {
QMessageBox::warning(0, QObject::tr("Database Error"),
mdb.lastError().text());
}else{
// 首次一定要指定 db
QSqlQuery q(mdb);
if(!mdb.tables().contains("student")){
T_INF <<"新建表格";
q.exec(QString("CREATE TABLE student (\
id INT PRIMARY KEY NOT NULL,\
name TEXT NOT NULL,\
age INT NOT NULL)"));
q.exec(QString("INSERT INTO student VALUES(1,'zhangsan',16)"));
q.exec(QString("INSERT INTO student VALUES(2,'lishi',17)"));
q.exec(QString("INSERT INTO student VALUES(3,'wangwu',16)"));
q.exec(QString("INSERT INTO student VALUES(4,'zhaolei',15)"));
}else{
T_INF <<"已经有表格了";
}
}
// 建立model
mmm = new MyModel(this,mdb);
}
MainWindow::~MainWindow()
{
mdb.close();
delete ui;
}
// add db
void MainWindow::on_pushButton_clicked()
{
if(QSqlDatabase::contains(CONN_NAME)){
T_INF <<"已经包含此连接名了:" << QString(CONN_NAME);
mdb = QSqlDatabase::database(CONN_NAME);
}
QSqlQuery q;
q.exec("select * from tb1"); // 故意用错表
if(q.last()){
T_INF <<"有数据:"<<q.at()+1;
}else{
T_ERR <<"没数据了";
}
T_INF <<"用model来查询看看 ==>> ";
mmm->openQuery();
}
MyModel::MyModel(QObject *parent, QSqlDatabase db):QSqlTableModel(parent,db)
{
}
void MyModel::openQuery()
{
QSqlQuery q;
if(!q.exec("select * from student")){
T_ERR <<"exec sql 错误";
}
if(q.last()){
T_INF <<"有数据:"<<q.at()+1;
}else{
T_ERR <<"没数据了";
}
}分别选择CONN_NAME一个编译并运行,结果如下:
1、CONN_NAME是字符串,结果:
[ TRACE ][file://..\mainwindow.cpp:38:MainWindow]使用自定义连接名:"connectionName" [ TRACE ][file://..\mainwindow.cpp:63:MainWindow]已经有表格了 [ TRACE ][file://..\mainwindow.cpp:82:on_pushButton_clicked]已经包含此连接名了:"connectionName" QSqlQuery::exec: database not open [ TRACE ][file://..\mainwindow.cpp:92:on_pushButton_clicked]没数据了 [ TRACE ][file://..\mainwindow.cpp:95:on_pushButton_clicked]用model来查询看看 ==>> QSqlQuery::exec: database not open [ TRACE ][file://..\mainwindow.cpp:110:openQuery]exec sql 错误 [ TRACE ][file://..\mainwindow.cpp:115:openQuery]没数据了
2、选择CONN_NAME为空,结果:
[ TRACE ][file://..\mainwindow.cpp:34:MainWindow]使用默认NULL连接名 [ TRACE ][file://..\mainwindow.cpp:63:MainWindow]已经有表格了 [ TRACE ][file://..\mainwindow.cpp:82:on_pushButton_clicked]已经包含此连接名了:"" [ TRACE ][file://..\mainwindow.cpp:92:on_pushButton_clicked]没数据了 [ TRACE ][file://..\mainwindow.cpp:95:on_pushButton_clicked]用model来查询看看 ==>> [ TRACE ][file://..\mainwindow.cpp:113:openQuery]有数据:4