一、简介
1、Qt SQL模块使用驱动程序插件操作不同的数据库。支持连接常用的数据库:MySQL、Oracle、SQL Server、SQLite。
其中,由于SQLite是轻量级的数据库,所以Qt支持创建生成本地SQLite数据库并管理。
2、QtSQL模块的api主要分为三层:
1)驱动层:包括类QSqlDriver、QSqlDriverCreator、QSqlDriverCreatorBase、QSqlDriverPlugin和QSqlResult。
2)数据库API层:这些类提供对数据库的访问。使用QSqlDatabase类进行连接。数据库交互是通过使用QSqlQuery类实现的。除了QSqlDatabase和QSqlQuery之外,QSqlError、QSqlField、QSqlIndex和QSqlRecord还支持SQL API层。
3)用户交互层:这些类将数据从数据库链接到数据库控件。它们包括QSqlQueryModel、QSqlTableModel和QSqlRelationalTableModel。
二、连接数据库
数据库连接通常由连接名标识,而不是由数据库名。可以有多个连接到同一个数据库。qt_sql_default_connection是默认的连接。
1、连接本地数据库:SQLite
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{
QAction *action = menuBar()->addAction("连接数据库");
connect(action,&QAction::triggered,[=]{
QSqlDatabase db;
//检测连接
if(QSqlDatabase::contains("qt_sql_default_connection")){
db = QSqlDatabase::database("qt_sql_default_connection");
}else{
//创建连接
db = QSqlDatabase::addDatabase("QSQLITE","qt_sql_default_connection");
db.setDatabaseName("F:/qtTest.db");
}
if(db.open()){
QMessageBox::information(this,"提示","数据库连接成功!");
db.close();
}else{
qDebug() << db.lastError().text();
}
});
}
2、连接远程数据库:MYSQL
遇到的问题:QSqlDatabase: QMYSQL driver not loaded 这是因为缺少libmysql.lib和libmysql.dll。网上给的链接已经下不到库了,只能自己去下载mysql的zip安装包,然后解压拿到这两个文件。当然release和debug版本都copy出来,然后放到QT的bin目录下即可。
MainWindow::MainWindow(QWidget *parent)
: QWidget(parent)
{
QFormLayout *mainLayout = new QFormLayout;
QLineEdit *host = new QLineEdit("localhost");
mainLayout->addRow("Host:",host);
QLineEdit *port = new QLineEdit("3306");
mainLayout->addRow("Port:",port);
QPushButton *login = new QPushButton("登录");
mainLayout->addWidget(login);
setLayout(mainLayout);
connect(login,&QPushButton::clicked,[=]{
connectToMySQL(host->text().trimmed(),port->text().trimmed().toInt());
});
}
MainWindow::~MainWindow()
{
}
void MainWindow::connectToMySQL(const QString &host, const int port)
{
QSqlDatabase db;
//检测是否已经存在默认连接了
if(QSqlDatabase::contains("qt_sql_default_connection")){
db = QSqlDatabase::database("qt_sql_default_connection");
}else{
//使用默认连接 创建一个sql对象
db = QSqlDatabase::addDatabase("QMYSQL","qt_sql_default_connection");
db.setDatabaseName("qtTest");
db.setHostName(host);
db.setPort(port);
db.setUserName("xxxx");
db.setPassword("xxxx");
}
bool ok = db.open();
if(ok){
qDebug() << "数据库连接成功";
//然后就可以操作数据库完成增删改查了
QSqlQuery query(db);
//开启事务
db.transaction();
QString sql = QString("CREATE TABLE IF NOT EXISTS Test (test VARCHAR(200))");
if(query.exec(sql)){
sql = QString("INSERT INTO Test VALUE('hello Qt!')");
if(query.exec(sql)){
db.commit();
qDebug() << "插入数据成功";
//关闭数据库连接
db.close();
}else{
db.rollback();
qDebug() << "插入数据失败:" << query.lastError().text();
}
}else{
qDebug() << "创建表失败:" << query.lastError().text();
db.rollback();
}
}else{
qDebug() << db.lastError().text();
}
}
3、优雅的删除多条数据库连接。
MainWindow::MainWindow(QWidget *parent)
: QWidget(parent)
{
QGridLayout *mainLayout = new QGridLayout;
mainLayout->addWidget(new QLabel("firstConnection"),0,0);
mainLayout->addWidget(new QLabel("secondConnection"),1,0);
mainLayout->addWidget(new QLabel("thirdConnection"),2,0);
QPushButton *connectBtn = new QPushButton("连接");
QPushButton *connectBtn1 = new QPushButton("连接1");
QPushButton *connectBtn2 = new QPushButton("连接2");
mainLayout->addWidget(connectBtn,0,1);
mainLayout->addWidget(connectBtn1,1,1);
mainLayout->addWidget(connectBtn2,2,1);
QPushButton *disconnectBtn = new QPushButton("断开连接");
QPushButton *disconnectBtn1 = new QPushButton("断开连接1");
QPushButton *disconnectBtn2 = new QPushButton("断开连接2");
mainLayout->addWidget(disconnectBtn,0,2);
mainLayout->addWidget(disconnectBtn1,1,2);
mainLayout->addWidget(disconnectBtn2,2,2);
QLabel *label = new QLabel("当前数据库连接条数:0");
mainLayout->addWidget(label,3,0,1,2);
connect(connectBtn,&QPushButton::clicked,[=]{
db = getDatabase("firstConnection");
if(db.open()){
QMessageBox::information(this,"提示","连接数据库成功");
label->setText(QString("当前数据库连接条数:%1").arg(QSqlDatabase::connectionNames().count()));
query = QSqlQuery(db);
QString sql = QString("CREATE TABLE IF NOT EXISTS Test (test VARCHAR(200))");
query.exec(sql);
}else{
QMessageBox::critical(this,"错误",db.lastError().text());
}
});
connect(connectBtn1,&QPushButton::clicked,[=]{
db1 = getDatabase("secondConnection");
if(db1.open()){
QMessageBox::information(this,"提示","连接数据库成功");
label->setText(QString("当前数据库连接条数:%1").arg(QSqlDatabase::connectionNames().count()));
query1 = QSqlQuery(db1);
QString sql = QString("CREATE TABLE IF NOT EXISTS Test1 (test VARCHAR(200))");
query1.exec(sql);
}else{
QMessageBox::critical(this,"错误",db1.lastError().text());
}
});
connect(connectBtn2,&QPushButton::clicked,[=]{
db2 = getDatabase("thirdConnection");
if(db2.open()){
QMessageBox::information(this,"提示","连接数据库成功");
label->setText(QString("当前数据库连接条数:%1").arg(QSqlDatabase::connectionNames().count()));
query2 = QSqlQuery(db2);
QString sql = QString("CREATE TABLE IF NOT EXISTS Test2 (test VARCHAR(200))");
query2.exec(sql);
}else{
QMessageBox::critical(this,"错误",db2.lastError().text());
}
});
connect(disconnectBtn,&QPushButton::clicked,[=]{
//错误写法 会被Qt警告 因为 连接是被引用计数的 在db 和 query那里还有计数 所以不会删除掉
// QSqlDatabase::removeDatabase("firstConnection");
//正确的写法
db = QSqlDatabase();
query = QSqlQuery();
QSqlDatabase::removeDatabase("firstConnection");
});
connect(disconnectBtn1,&QPushButton::clicked,[=]{
//错误写法 会被Qt警告 因为 连接是被引用计数的 在db1 和 query1那里还有计数 所以不会删除掉
// QSqlDatabase::removeDatabase("secondConnection");
//正确的写法
db1 = QSqlDatabase();
query1 = QSqlQuery();
QSqlDatabase::removeDatabase("secondConnection");
});
connect(disconnectBtn2,&QPushButton::clicked,[=]{
//错误写法 会被Qt警告 因为 连接是被引用计数的 在db2 和 query2那里还有计数 所以不会删除掉
// QSqlDatabase::removeDatabase("thirdConnection");
//正确的写法
db2 = QSqlDatabase();
query2 = QSqlQuery();
QSqlDatabase::removeDatabase("thirdConnection");
});
setLayout(mainLayout);
}
MainWindow::~MainWindow()
{
db.close();
db1.close();
db2.close();
}
QSqlDatabase MainWindow::getDatabase(const QString &connection)
{
QSqlDatabase db;
if(QSqlDatabase::contains(connection)){
QMessageBox::warning(this,"警告",QString("连接:%1 ,已经存在,请勿重复连接").arg(connection));
db = QSqlDatabase::database(connection);
}else{
db = QSqlDatabase::addDatabase("QSQLITE",connection);
db.setDatabaseName("F:/qtTest.db");
}
return db;
}
三、操作数据库
两种方式:
第一种:自己写sql,然后用QSqlQuery执行,之后的结果用QSqlQuery::next(),QSqlQuery::value()来获取sql结果值
第二种:自己写sql,然后用QSqlQuery执行,之后的结果用QSqlQuery::next(),QSqlField, QSqlIndex, and QSqlRecord.来获取
具体操作的用法详见:https://www.cnblogs.com/xia-weiwen/archive/2017/05/04/6806709.html
批量操作也比较常用:https://blog.csdn.net/phenixyf/article/details/70598244
四、访问数据库的方便控件类。