结论:
只有使用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_H
CPP:
#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