一、架构层次
用户接口层
- QSqlQueryModel:管理SQL查询结果,提供表格数据模型用于展示
- QSqlTableModel:支持直接操作数据库表(增删改查)
- QSqlRelationalTableModel:支持带外键关联的复杂表操作
SQL接口层
- QSqlDatabase:创建和管理数据库连接
- QSqlQuery:执行SQL语句和遍历结果集
- QSqlRecord:封装数据库记录操作(字段管理)
驱动层
支持多种数据库驱动插件(QSQLITE、QMYSQL等),通过抽象接口实现跨数据库兼容
二、Qt支持的数据库类型
- SQLite
Qt内置支持SQLite数据库,无需额外安装驱动,适合嵌入式和小型应用。 - MySQL/Oracle/SQL Server
需安装对应数据库驱动模块(如QMYSQL、QODBC等),支持通过ODBC或原生驱动连接。 - 其他数据库
包括PostgreSQL等,需通过QSqlDatabase::drivers()
查看当前支持的驱动列表。
三、数据库连接步骤
- 添加SQL模块
在项目配置文件(.pro
)中添加:QT += sql
- 加载驱动并创建连接
QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE"); // SQLite示例 db.setDatabaseName("my.db"); // 设置数据库文件路径 if (!db.open()) { qDebug() << "连接失败:" << db.lastError().text(); }
- 多数据库连接
通过指定不同连接名实现多个数据库同时操作:QSqlDatabase db1 = QSqlDatabase::addDatabase("QSQLITE", "connection1"); QSqlDatabase db2 = QSqlDatabase::addDatabase("QMYSQL", "connection2");
四、基本数据库操作
执行SQL语句
使用QSqlQuery
执行增删改查操作:QSqlQuery query; query.exec("CREATE TABLE user (id INT PRIMARY KEY, name TEXT)"); // 创建表 query.exec("INSERT INTO user VALUES (1, 'Alice')"); // 插入数据
查询数据
if (query.exec("SELECT * FROM user")) { while (query.next()) { int id = query.value("id").toInt(); QString name = query.value("name").toString(); } }
预处理语句(防SQL注入)
query.prepare("INSERT INTO user (id, name) VALUES (:id, :name)"); query.bindValue(":id", 2); query.bindValue(":name", "Bob"); query.exec();
五、高级功能
事务处理
db.transaction(); // 执行多条SQL操作 if (操作成功) db.commit(); else db.rollback();
模型-视图架构
使用QSqlTableModel
或QSqlQueryModel
实现数据与UI组件的绑定:QSqlTableModel *model = new QSqlTableModel(this); model->setTable("user"); model->select(); tableView->setModel(model);
六、注意事项
- 驱动兼容性
确保目标平台已安装对应数据库驱动(如Windows需libmysql.dll
)。 - 错误处理
通过QSqlError
捕获并处理数据库操作中的异常。 - 性能优化
批量操作建议使用事务,避免频繁打开/关闭连接。 - 中文乱码
在连接字符串中添加;Charset=UTF8;
,确保数据库字段使用NVARCHAR。
七、MS SQL SERVER
在Qt中操作Microsoft SQL Server,你可以使用多种方法,包括使用ODBC(Open Database Connectivity)连接,或者使用专门的库如QODBC或QSqlServer(如果你使用的是Qt 5或更高版本,并且有对应的插件)。以下是两种常见的方法:
方法1:使用QODBC
1)确保你的系统安装了ODBC驱动:
对于Windows,通常SQL Server ODBC驱动已经预装。你可以在ODBC数据源管理器中检查这一点。
2)在Qt项目中配置ODBC连接:
如果你使用的是Qt 5或更高版本,并且你的系统上安装了SQL Server ODBC驱动,你可以直接使用QODBC驱动。
3)连接数据库代码:
#include <QSqlDatabase>
#include <QDebug>
int main() {
QSqlDatabase db = QSqlDatabase::addDatabase("QODBC");
db.setHostName("你的服务器名"); // 例如 localhost 或 IP 地址
db.setDatabaseName("你的数据库名");
db.setUserName("你的用户名");
db.setPassword("你的密码");
if (!db.open()) {
qDebug() << "无法打开数据库:" << db.lastError().text();
return -1;
}
qDebug() << "数据库连接成功!";
// 执行查询等操作...
return 0;
}
方法2:使用QSqlServer
如果你使用的是Qt 5.7或更高版本,可以直接使用QSqlServer驱动,而无需ODBC。
1)确保你的Qt版本支持QSqlServer:
2)连接数据库代码:
#include <QSqlDatabase>
#include <QDebug>
int main() {
QSqlDatabase db = QSqlDatabase::addDatabase("QSQLSERVER");
db.setHostName("你的服务器名"); // 例如 localhost 或 IP 地址 (对于本地服务器可以留空)
db.setDatabaseName("你的数据库名"); // 不需要加前缀例如"数据库名"而不是"Driver={SQL Server};Server=服务器名;Database=数据库名;"
db.setUserName("你的用户名");
db.setPassword("你的密码");
if (!db.open()) {
qDebug() << "无法打开数据库:" << db.lastError().text();
return -1;
}
qDebug() << "数据库连接成功!";
// 执行查询等操作...
return 0;
}
完整实例代码:
1)数据库连接类 DatabaseManager.h
#include <QSqlDatabase>
#include <QSqlQuery>
#include <QSqlError>
#include <QDebug>
class DatabaseManager {
public:
static bool connect() {
QSqlDatabase db = QSqlDatabase::addDatabase("QODBC");
QString connectionString =
"DRIVER={SQL Server};"
"SERVER=YourPC\\YourInstance;" // 命名实例写法
"DATABASE=TestDB;"
"UID=sa;"
"PWD=YourPassword;";
db.setDatabaseName(connectionString);
if (!db.open()) {
qDebug() << "连接失败:" << db.lastError().text();
return false;
}
qDebug() << "数据库连接成功!";
return true;
}
static void disconnect() {
QSqlDatabase::database().close();
}
};
连接字符串示例
"DRIVER={SQL Server};SERVER=MyPC\\MyInstance,5000;DATABASE=MyDB;UID=sa;PWD=123456;"
2)主窗口类 MainWindow.cpp(含增删改查、事务处理)
#include "MainWindow.h"
#include "ui_MainWindow.h"
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) {
ui->setupUi(this);
DatabaseManager::connect(); // 初始化连接
loadDataToTable(); // 加载数据到表格
}
MainWindow::~MainWindow() {
DatabaseManager::disconnect();
delete ui;
}
// 加载数据到表格
void MainWindow::loadDataToTable() {
QSqlQuery query;
query.exec("SELECT * FROM Users");
ui->tableWidget->setRowCount(0);
while (query.next()) {
int row = ui->tableWidget->rowCount();
ui->tableWidget->insertRow(row);
ui->tableWidget->setItem(row, 0, new QTableWidgetItem(query.value("ID").toString()));
ui->tableWidget->setItem(row, 1, new QTableWidgetItem(query.value("Name").toString()));
ui->tableWidget->setItem(row, 2, new QTableWidgetItem(query.value("Age").toString()));
}
}
// 添加用户
void MainWindow::on_btnAdd_clicked() {
QSqlQuery query;
query.prepare("INSERT INTO Users (Name, Age) VALUES (?, ?)");
query.addBindValue(ui->txtName->text());
query.addBindValue(ui->txtAge->text().toInt());
if (!query.exec()) {
qDebug() << "插入失败:" << query.lastError().text();
} else {
loadDataToTable(); // 刷新表格
}
}
// 删除用户
void MainWindow::on_btnDelete_clicked() {
int selectedRow = ui->tableWidget->currentRow();
if (selectedRow == -1) return;
QString id = ui->tableWidget->item(selectedRow, 0)->text();
QSqlQuery query;
query.prepare("DELETE FROM Users WHERE ID = ?");
query.addBindValue(id);
if (!query.exec()) {
qDebug() << "删除失败:" << query.lastError().text();
} else {
loadDataToTable(); // 刷新表格
}
}
// 执行事务处理示例
void MainWindow::on_btnTransaction_clicked() {
QSqlDatabase::database().transaction(); // 开启事务
QSqlQuery query;
query.exec("UPDATE Users SET Age = Age + 1 WHERE Name = 'Alice'");
query.exec("UPDATE Users SET Age = Age - 1 WHERE Name = 'Bob'");
if (query.lastError().isValid()) {
QSqlDatabase::database().rollback(); // 回滚
qDebug() << "事务执行失败,已回滚";
} else {
QSqlDatabase::database().commit(); // 提交
qDebug() << "事务执行成功";
}
}
八、MY SQL
1)数据库连接类 DatabaseManager.h
#include <QSqlDatabase>
#include <QSqlQuery>
#include <QSqlError>
#include <QDebug>
class DatabaseManager {
public:
static bool connect() {
QSqlDatabase db = QSqlDatabase::addDatabase("QMYSQL");
db.setHostName("localhost"); // MySQL 服务器地址
db.setPort(3306); // MySQL 默认端口
db.setDatabaseName("TestDB"); // 数据库名
db.setUserName("qtuser"); // 用户名
db.setPassword("123456"); // 密码
if (!db.open()) {
qDebug() << "连接失败:" << db.lastError().text();
return false;
}
qDebug() << "数据库连接成功!";
return true;
}
static void disconnect() {
QSqlDatabase::database().close();
}
};
2)主窗口类 MainWindow.cpp
(含增删改查、事务处理)
#include "MainWindow.h"
#include "ui_MainWindow.h"
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) {
ui->setupUi(this);
DatabaseManager::connect();
loadDataToTable(); // 初始化加载数据
}
MainWindow::~MainWindow() {
DatabaseManager::disconnect();
delete ui;
}
// 加载数据到表格
void MainWindow::loadDataToTable() {
QSqlQuery query("SELECT * FROM Users");
ui->tableWidget->setRowCount(0);
while (query.next()) {
int row = ui->tableWidget->rowCount();
ui->tableWidget->insertRow(row);
ui->tableWidget->setItem(row, 0, new QTableWidgetItem(query.value("ID").toString()));
ui->tableWidget->setItem(row, 1, new QTableWidgetItem(query.value("Name").toString()));
ui->tableWidget->setItem(row, 2, new QTableWidgetItem(query.value("Age").toString()));
}
}
// 添加用户
void MainWindow::on_btnAdd_clicked() {
QSqlQuery query;
query.prepare("INSERT INTO Users (Name, Age) VALUES (?, ?)");
query.addBindValue(ui->txtName->text());
query.addBindValue(ui->txtAge->text().toInt());
if (!query.exec()) {
qDebug() << "插入失败:" << query.lastError().text();
} else {
loadDataToTable(); // 刷新表格
}
}
// 删除用户
void MainWindow::on_btnDelete_clicked() {
int row = ui->tableWidget->currentRow();
if (row == -1) return;
QString id = ui->tableWidget->item(row, 0)->text();
QSqlQuery query;
query.prepare("DELETE FROM Users WHERE ID = ?");
query.addBindValue(id);
if (!query.exec()) {
qDebug() << "删除失败:" << query.lastError().text();
} else {
loadDataToTable(); // 刷新表格
}
}
// 更新用户年龄
void MainWindow::on_btnUpdate_clicked() {
int row = ui->tableWidget->currentRow();
if (row == -1) return;
QString id = ui->tableWidget->item(row, 0)->text();
int newAge = ui->txtNewAge->text().toInt();
QSqlQuery query;
query.prepare("UPDATE Users SET Age = ? WHERE ID = ?");
query.addBindValue(newAge);
query.addBindValue(id);
if (!query.exec()) {
qDebug() << "更新失败:" << query.lastError().text();
} else {
loadDataToTable(); // 刷新表格
}
}
void MainWindow::on_btnTransaction_clicked() {
QSqlDatabase::database().transaction(); // 开启事务
QSqlQuery query;
query.exec("UPDATE Users SET Age = Age + 1 WHERE Name = 'Alice'");
query.exec("UPDATE Users SET Age = Age - 1 WHERE Name = 'Bob'");
if (query.lastError().isValid()) {
QSqlDatabase::database().rollback();
qDebug() << "事务回滚!";
} else {
QSqlDatabase::database().commit();
qDebug() << "事务提交!";
}
}
九、SQLITE
1)数据库连接类 DatabaseManager.h
#include <QSqlDatabase>
#include <QSqlQuery>
#include <QSqlError>
#include <QDebug>
#include <QStandardPaths>
class DatabaseManager {
public:
static bool connect() {
// 数据库文件路径(自动创建)
QString dbPath = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + "/mydatabase.db";
QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");
db.setDatabaseName(dbPath);
if (!db.open()) {
qDebug() << "连接失败:" << db.lastError().text();
return false;
}
qDebug() << "数据库连接成功!路径:" << dbPath;
// 自动建表
createTables();
return true;
}
static void createTables() {
QSqlQuery query;
query.exec("CREATE TABLE IF NOT EXISTS Users ("
"ID INTEGER PRIMARY KEY AUTOINCREMENT,"
"Name TEXT NOT NULL,"
"Age INTEGER)");
if (query.lastError().isValid()) {
qDebug() << "建表失败:" << query.lastError().text();
}
}
static void disconnect() {
QSqlDatabase::database().close();
}
};
2)
主窗口类 MainWindow.cpp(含增删改查、事务处理)
#include "MainWindow.h"
#include "ui_MainWindow.h"
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) {
ui->setupUi(this);
DatabaseManager::connect();
loadDataToTable(); // 初始化加载数据
}
MainWindow::~MainWindow() {
DatabaseManager::disconnect();
delete ui;
}
// 加载数据到表格
void MainWindow::loadDataToTable() {
QSqlQuery query("SELECT * FROM Users");
ui->tableWidget->setRowCount(0);
while (query.next()) {
int row = ui->tableWidget->rowCount();
ui->tableWidget->insertRow(row);
ui->tableWidget->setItem(row, 0, new QTableWidgetItem(query.value("ID").toString()));
ui->tableWidget->setItem(row, 1, new QTableWidgetItem(query.value("Name").toString()));
ui->tableWidget->setItem(row, 2, new QTableWidgetItem(query.value("Age").toString()));
}
}
// 添加用户
void MainWindow::on_btnAdd_clicked() {
QSqlQuery query;
query.prepare("INSERT INTO Users (Name, Age) VALUES (:name, :age)");
query.bindValue(":name", ui->txtName->text());
query.bindValue(":age", ui->txtAge->text().toInt());
if (!query.exec()) {
qDebug() << "插入失败:" << query.lastError().text();
} else {
loadDataToTable(); // 刷新表格
}
}
// 删除用户
void MainWindow::on_btnDelete_clicked() {
int row = ui->tableWidget->currentRow();
if (row == -1) return;
QString id = ui->tableWidget->item(row, 0)->text();
QSqlQuery query;
query.prepare("DELETE FROM Users WHERE ID = ?");
query.addBindValue(id);
if (!query.exec()) {
qDebug() << "删除失败:" << query.lastError().text();
} else {
loadDataToTable(); // 刷新表格
}
}
// 更新用户年龄
void MainWindow::on_btnUpdate_clicked() {
int row = ui->tableWidget->currentRow();
if (row == -1) return;
QString id = ui->tableWidget->item(row, 0)->text();
int newAge = ui->txtNewAge->text().toInt();
QSqlQuery query;
query.prepare("UPDATE Users SET Age = ? WHERE ID = ?");
query.addBindValue(newAge);
query.addBindValue(id);
if (!query.exec()) {
qDebug() << "更新失败:" << query.lastError().text();
} else {
loadDataToTable(); // 刷新表格
}
}
// 批量插入数据(事务加速)
void MainWindow::on_btnBatchInsert_clicked() {
QSqlDatabase::database().transaction(); // 开启事务
QSqlQuery query;
query.prepare("INSERT INTO Users (Name, Age) VALUES (?, ?)");
for (int i = 0; i < 1000; ++i) {
query.addBindValue("User_" + QString::number(i));
query.addBindValue(20 + i % 10);
query.exec();
}
if (query.lastError().isValid()) {
QSqlDatabase::database().rollback();
qDebug() << "批量插入失败,已回滚";
} else {
QSqlDatabase::database().commit();
qDebug() << "批量插入成功,耗时优化 10x+";
loadDataToTable();
}
}
十、ORACLE
在使用Qt进行Oracle数据库操作时,通常有两种方法比较常见:使用Oracle的OCI(Oracle Call Interface)或者使用ODBC(Open Database Connectivity)。下面我将详细介绍如何使用这两种方法在Qt应用程序中操作Oracle数据库。
方法1:使用OCI
Oracle Call Interface (OCI) 是Oracle提供的一套C语言API,用于访问Oracle数据库。要在Qt中使用OCI,你需要先确保你的系统上安装了Oracle的客户端库和头文件,并且你的项目需要链接到这些库。
步骤:
1)Oracle 客户端安装
下载 Oracle Instant Client 的 Basic 和 SDK 包(需与 Qt 编译器位数一致)。解压到目录如 C:\oracle\instantclient_12_2
,将 oci.dll
所在路径加入系统环境变量 PATH
2)Qt OCI 驱动编译
cd Qt/6.5.0/Src/qtbase/src/plugins/sqldrivers/oci
qmake "INCLUDEPATH+=C:/oracle/instantclient_12_2/sdk/include" "LIBS+=-LC:/oracle/instantclient_12_2 -loci"
nmake # 或make
编译生成的 qsqloci.dll
需复制到 Qt/6.5.0/mingw_64/plugins/sqldrivers
3)在Qt项目中包含头文件和链接库:
#include <oci.h>
4) 在.pro
文件中添加链接器选项:
QT += core gui sql
CONFIG += c++17
# 配置 Oracle 库路径
win32 {
LIBS += -LC:/oracle/instantclient_12_2 -loci
INCLUDEPATH += C:/oracle/instantclient_12_2/sdk/include
}
完整实例代码:
1)数据库连接类 OracleManager.h
#include <QSqlDatabase>
#include <QSqlQuery>
#include <QSqlError>
#include <QDebug>
class OracleManager {
public:
static bool connect(const QString &serviceName) {
QSqlDatabase db = QSqlDatabase::addDatabase("QOCI");
db.setHostName("192.168.1.100"); // Oracle 服务器 IP
db.setPort(1521); // 默认端口
db.setDatabaseName(serviceName); // 服务名(非 SID)
db.setUserName("scott"); // 用户名
db.setPassword("tiger"); // 密码
if (!db.open()) {
qDebug() << "[ERROR] 连接失败:" << db.lastError().text() << ":ml-citation{ref="1,6" data="citationList"}";
return false;
}
qDebug() << "数据库连接成功!";
return true;
}
static void disconnect() {
QSqlDatabase::database().close();
}
};
2)
主窗口类 MainWindow.cpp(含增删改查、事务处理)
// 创建表
void MainWindow::createTable() {
QSqlQuery query;
query.exec("CREATE TABLE Employees ("
"EmpID NUMBER PRIMARY KEY,"
"Name NVARCHAR2(50),"
"Salary NUMBER(10,2))");
if(query.lastError().isValid())
qDebug() << "建表错误:" << query.lastError().text() << ":ml-citation{ref="8" data="citationList"}";
}
// 插入数据(绑定参数)
void MainWindow::onInsertClicked() {
QSqlQuery query;
query.prepare("INSERT INTO Employees (EmpID, Name, Salary) VALUES (:id, :name, :sal)");
query.bindValue(":id", 1001);
query.bindValue(":name", "张三");
query.bindValue(":sal", 8500.50);
if (!query.exec())
qDebug() << "插入失败:" << query.lastError().text() << ":ml-citation{ref="3,6" data="citationList"}";
}
// 查询数据(事务处理)
void MainWindow::onQueryClicked() {
QSqlDatabase::database().transaction();
QSqlQuery query("SELECT * FROM Employees");
while (query.next()) {
int id = query.value("EmpID").toInt();
QString name = query.value("Name").toString();
double salary = query.value("Salary").toDouble();
// 显示到 UI...
}
if (query.lastError().isValid()) {
QSqlDatabase::database().rollback();
qDebug() << "事务回滚!" << ":ml-citation{ref="8" data="citationList"}";
} else {
QSqlDatabase::database().commit();
}
}
方法2:使用ODBC
ODBC提供了一个数据库无关的应用程序编程接口(API),允许应用程序通过ODBC驱动程序与数据库进行通信。Qt提供了对ODBC的支持,可以通过QSqlDatabase
和QSqlQuery
类来操作。
QSqlDatabase db = QSqlDatabase::addDatabase("QODBC");
db.setHostName("hostname"); // 通常是localhost或服务器地址
db.setDatabaseName("DSN_NAME"); // 数据源名称,在ODBC中配置的DSN名称
db.setUserName("username");
db.setPassword("password");
if (db.open()) {
QSqlQuery query(db);
query.exec("SELECT * FROM your_table");
while (query.next()) {
// 处理查询结果...
}
db.close();
} else {
qDebug() << "Database connection failed";
}