QT学习第八课

目录

1. 准备工作

2. 连接数据库

3. 创建表

4. 增删改

5. 查询


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();
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值