目录
1. 准备工作
Qt本身没有数据库功能,但是Qt支持调用其他主流的数据库产品,并且为这些数据库产品指定了统一的接口,实际上是数据库的中间件。
Qt支持以下数据库类型:
嵌入式常用的数据库是SQLite3,本体只有几兆大小,非常适合集成到嵌入式产品,在Qt5以上版本也集成了SQLite数据库,因此可以直接通过驱动的名称直接连接SQLite数据库。
数据库的编程需要用到以下几个相关类:
● QSqlDatabase
数据库连接类,表示一个数据库的连接。
● QSqlQuery
数据库操作类,可以操作SQL语句。
● QSqlError
数据库错误信息类,用户收集数据库底层数据传递到上层来获取错误信息。
数据库相关类无法直接使用,需要在.pro项目配置文件中添加sql模块。
2. 连接数据库
主要通过QSqlDatabase相关函数实现:
// 获得一个数据库连接对象
// 参数为数据类型,详见本章第一节表格
// 返回值为连接的对象
QSqlDatabase QSqlDatabase::addDatabase(const QString & type)
// 设置数据库名称
// 参数因不同的数据库表示不同的含义,对于SQLITE,此参数表示数据文件名,此文件会在项目的构建目录中生成
void QSqlDatabase::setDatabaseName(const QString & name)
// 打开数据库连接
// 返回值是连接打开的结果,如果打开失败,可以通过QSqlError类的lastError函数来获得错误信息
bool QSqlDatabase::open()
// 返回上一次的错误信息的封装类
QSqlError QSqlDatabase::lastError() const
// 从QSqlError中提取错误文本信息
QString QSqlError::text() const
连接成功后,可以在构建目录看到对应的数据库文件。
在构造函数中开启数据库连接,在析构函数中关闭数据库连接。
// 关闭数据库连接
void QSqlDatabase::close()
// 返回数据库的打开状态
bool QSqlDatabase::isOpen() const
3. 创建表
建表语句:
CREATE TABLE book(id INTEGER PRIMARY KEY,name TEXT,price REAL,author TEXT);
CREATE TABLE book(
id INTEGER PRIMARY KEY,
name TEXT,
price REAL,
author TEXT);
// 执行SQL 语句
// 参数为执行的SQL语句
// 返回值为执行的结果
bool QSqlQuery::exec(const QString & query)
// 与本章第二节用法一致
QSqlError QSqlQuery::lastError() const
一个操作SQLite的可视化软件:
通过网盘分享的文件:SQLiteSpy.exe
下载链接: https://pan.baidu.com/s/1SPPLwafxlO2RxS3MB-gH1A?pwd=ofer 提取码: ofer
--来自百度网盘超级会员v1的分享
建表成功后,可以使用SQLiteSpy打开数据库查看表结构是否成功:
4. 增删改
增删改操作都需要先录入用户输入,然后把用户的输入的数据组装成SQL语句,最后执行。
组装SQL语句有两种方式:
● 字符串拼接
这种方法虽然原理简单,但是容易拼接出错,且安全性较低。
https://zhuanlan.zhihu.com/p/151653049
● 预处理+占位符
推荐使用这种方式,这种方式需要先编辑有占位符的预处理SQL语句,交给Qt,Qt内部就知道要执行的SQL语句格式。然后在进行参数与占位符的替换,最终执行。
占位符有两种风格:
➢ Oracle风格
使用 :字段 格式
例:根据ID更改其他三个属性
UPDATE book SET name=:name,price=:price,author=:author WHERE id=:id;
➢ ODBC风格
使用?的格式
例:增加一个图书数据
INSERT INTO book VALUES(?,?,?,?);
相关函数如下
// 预处理SQL语句,此时SQL语句并没有执行,只是送到Qt内部
// 参数就是要预处理的SQL语句
// 返回值为预处理的结果
bool QSqlQuery::prepare(const QString & query)
// 绑定ODBC风格的占位符参数,绑定时一定要注意参数顺序
// 参数为要绑定的数据
void QSqlQuery::addBindValue(const QVariant & val)
// 绑定oracle风格占位符,绑定时可以乱序
// 参数1 占位符
// 参数2 要绑定的数据
void QSqlQuery::bindValue(const QString & placeholder, const QVariant & val)
5. 查询
// 判断查询结果有无数据,如果有则向后移动游标并取出,没有则返回false
bool QSqlQuery::next()
// 按照字段编号来取出相应的值,序号从0开始
// 返回值QVariant类型,可以依据需要直接转换成需要的值
QVariant QSqlQuery::value(int index) const
// 按照字段取出对应的值
// 返回值QVariant类型,可以依据需要直接转换成需要的值
QVariant QSqlQuery::value(const QString & name) const
可以使用LIKE关键字配合通配符实现模糊查询:
● %
任意多个(0,1,.....,n)字符
● _
任意一个字符
【例子】查询树子辈的人员信息
SELECT * FROM class24011 WHERE name LIKE "_树%";
【例子】查询名字中包含艳的人员信息
SELECT * FROM class24011 WHERE name LIKE "%艳%";
dialog.h
#ifndef DIALOG_H
#define DIALOG_H
#include <QDialog>
#include <QButtonGroup>
#include <QSqlDatabase> // 连接数据库
#include <QSqlError> // 数据库错误信息类
#include <QDebug>
#include <QMessageBox>
#include <QSqlQuery>
namespace Ui {
class Dialog;
}
class Dialog : public QDialog
{
Q_OBJECT
public:
explicit Dialog(QWidget *parent = 0);
~Dialog();
private:
Ui::Dialog *ui;
QButtonGroup *group;
void connect2DB(); // 连接到数据库
void createTable(); // 建表
QSqlDatabase db;
void insertData(); // 插入数据
void deleteData(); // 按编号删除数据
void updateData(); // 按编号修改数据
void selectAll(); // 全查
bool isDataExists(); // 根据ID查询
void selectLike(); // 对书名模糊查询
private slots:
void btnsClickedSlot(int);
};
#endif // DIALOG_H
dialog.cpp
#include "dialog.h"
#include "ui_dialog.h"
Dialog::Dialog(QWidget *parent) :
QDialog(parent),
ui(new Ui::Dialog)
{
ui->setupUi(this);
group = new QButtonGroup(this);
group->addButton(ui->pushButtonInsert,1);
group->addButton(ui->pushButtonDelete,2);
group->addButton(ui->pushButtonUpdate,3);
group->addButton(ui->pushButtonSelect,4);
connect(group,SIGNAL(buttonClicked(int)),
this,SLOT(btnsClickedSlot(int)));
connect2DB();
}
Dialog::~Dialog()
{
// 如果数据库连接还在打开,则关闭
if(db.isOpen())
db.close();
delete ui;
}
void Dialog::connect2DB()
{
// 创建连接对象
db = QSqlDatabase::addDatabase("QSQLITE");
// 设置数据库名称
db.setDatabaseName("book_management.db");
// 打开数据库
if(db.open())
{
qDebug() << "连接成功";
createTable();
selectAll();
}
else
{
// 获得错误信息封装类
QSqlError info = db.lastError();
// 获取错误信息
QString text = info.text();
// 展示错误
QMessageBox::critical(this,"错误",text);
}
}
void Dialog::createTable()
{
QString sql = "CREATE TABLE book(id INTEGER PRIMARY KEY,name TEXT,price REAL,author TEXT);";
// 创建数据库操作类对象
QSqlQuery sq;
if(sq.exec(sql))
{
qDebug() << "建表成功!";
}
else
{
// 获得错误信息封装类
QSqlError info = sq.lastError();
// 获取错误信息
QString text = info.text();
// 展示错误
qDebug() << "建表失败!" << text;
}
}
void Dialog::insertData()
{
// 获得用户输入
int id = ui->spinBox->value();
QString name = ui->lineEditName->text();
if(name == "")
{
QMessageBox::warning(this,"提示","请输入书名");
return;
}
double price = ui->doubleSpinBox->value();
QString author = ui->lineEditAuthor->text();
if(author == "")
{
QMessageBox::warning(this,"提示","请输入作者名");
return;
}
// 创建预处理语句
QString sql = "INSERT INTO book VALUES(?,?,?,?);";
QSqlQuery sq;
sq.prepare(sql);
sq.addBindValue(id);
sq.addBindValue(name);
sq.addBindValue(price);
sq.addBindValue(author);
// 执行绑定后的语句
if(sq.exec())
{
QMessageBox::information(this,"通知","插入信息成功!");
selectAll();
}
else// 失败
{
// 获得错误信息封装类
QSqlError info = sq.lastError();
// 获取错误信息
QString text = info.text();
// 展示错误
text.prepend("数据插入失败:");
QMessageBox::warning(this,"提示",text);
}
}
void Dialog::deleteData()
{
int id = ui->spinBox->value();
//判断要删除的内容在不在
if(!isDataExists())
{
QMessageBox::warning(this,"警告","输入的ID不存在");
return;
}
QString sql = "DELETE FROM book WHERE id=?";
QSqlQuery sq;
sq.prepare(sql);
// 绑定参数
sq.addBindValue(id);
// 执行绑定后的SQL语句
if(sq.exec())
{
QMessageBox::information(this,"通知","数据删除成功!");
selectAll();
}
else// 失败
{
QSqlError info = sq.lastError();
QString text = info.text();
text.prepend("数据删除失败:");
QMessageBox::warning(this,"警告",text);
}
}
void Dialog::updateData()
{
// 获得用户数据
QString name = ui->lineEditName->text();
if(name == "")
{
QMessageBox::warning(this,"提示","请输入书名!");
return;
}
QString author = ui->lineEditAuthor->text();
if(author == "")
{
QMessageBox::warning(this,"提示","请输入作者名!");
return;
}
int id = ui->spinBox->value();
double price = ui->doubleSpinBox->value();
// 判断更新的数据在不在
if(!isDataExists())
{
QMessageBox::warning(this,"警告","输入的ID不存在");
return;
}
// 预处理语句(Oracle风格)
QString sql = "UPDATE book SET name=:name,price=:price,author=:author WHERE id=:id;";
// 预处理
QSqlQuery sq;
sq.prepare(sql);// 预处理
// 绑定参数(可以乱序)
sq.bindValue(":id",id);
sq.bindValue(":author",author);
sq.bindValue(":price",price);
sq.bindValue(":name",name);
if(sq.exec())
{
QMessageBox::information(this,"通知","数据更新成功!");
selectAll();
}
else
{
QSqlError info = sq.lastError();
QString text = info.text();
text.prepend("数据更新失败!");
QMessageBox::warning(this,"警告",text);
}
}
void Dialog::selectAll()
{
QString sql = "SELECT * FROM book";
QSqlQuery sq;
if(sq.exec(sql))
{
// 清空上次显示
ui->textBrowser->clear();
while(sq.next())// 循环取出
{
// 取出每一条记录中的字段值
QString id = sq.value(0).toString();
QString name = sq.value("name").toString();
QString price = sq.value(2).toString();
QString author = sq.value(3).toString();
// 显示
QString text = id.append("-") + name.append("-") + price.append("-") + author;
ui->textBrowser->append(text);
}
}
else
{
QSqlError info = sq.lastError();
QString text = info.text();
text.prepend("查询失败!");
QMessageBox::warning(this,"警告",text);
}
}
bool Dialog::isDataExists()
{
QString idText = QString::number(ui->spinBox->value());
QString sql = "SELECT * FROM book WHERE id=";
sql.append(idText);// 字符串拼接,只为证明能用,但是不建议
QSqlQuery sq;
if(sq.exec(sql))
{
return sq.next();
}
else
{
return false;
}
}
void Dialog::selectLike()
{
// 获得用户输入的数据
QString name = ui->lineEditName->text();
if(name == "")
{
QMessageBox::warning(this,"提示","请输入书名!");
return;
}
// ODBC 预处理SQL
QString sql = "SELECT * FROM book WHERE name LIKE ?";
QSqlQuery sq;
// 预处理
sq.prepare(sql);
sq.addBindValue(name.append("%").prepend("%")); // 绑定并添加通配符
if(sq.exec())
{
// 清空上次显示
ui->textBrowser->clear();
while(sq.next())
{
// 取出每一条记录中的字段值
QString id = sq.value(0).toString();
QString name = sq.value("name").toString();
QString price = sq.value(2).toString();
QString author = sq.value(3).toString();
// 显示
QString text = id.append("-") + name.append("-") + price.append("-") + author;
ui->textBrowser->append(text);
}
}
else
{
QSqlError info = sq.lastError();
QString text = info.text();
text.prepend("查询失败!");
QMessageBox::warning(this,"警告",text);
}
}
void Dialog::btnsClickedSlot(int id)
{
if(id == 1)
{
insertData();
}
else if(id == 2)
{
deleteData();
}
else if(id == 3)
{
updateData();
}
else if(id == 4)
{
selectLike();
}
}