嵌入式学习-QT-Day08
八、数据库
1、准备工作
2、连接数据库
3、创建表
4、增删改
5、查询
5.1 全查
5.2 模糊查询
八、数据库
1、准备工作
Qt本身并没有数据库的功能,但是Qt支持调用其他主流的数据库产品,并且这些数据库产品指定了统一的Qt接口,实际上使一种数据库的中间件。
Qt支持以下数据库类型。
嵌入式常用的数据库是SQLite3,本体只有几兆大小,非常适合集成到嵌入式产品当中。在Qt5版本及其以上也集成了SQLite数据库,因此可以直接通过驱动名称连接SQLite。
数据库编程中需要用到以下几个相关类:
- QSqlDatabase
数据库相关类,用于一个数据库的连接。
- QSqlQuery
数据库的操作类,可以操作SQL语句。
- QSqlError
数据库操作信息类,用户手机数据库底层传递到Qt中的错误信息的。
数据库的相关产品无法直接使用,需要在.pro项目配置文件中添加sql模块。
添加完成后保存。
2、连接数据库
主要通过QsqlDatabase类进行连接,相关函数实现:
// 获得一个数据库连接对象
// 参数为数据库类型,详见本章第一节表格(注意大小写)
// 返回值:为连接对象
QSqlDatabase QSqlDatabase::addDatabase(const QString & type)[static]
// 设置数据库名称
// 参数:要设置的数据库名称。对于SQLite,此函数表示数据库文件名。此文件会在项目目录中生成。
void QSqlDatabase::setDatabaseName(const QString & name)
// 打开数据库连接
// 返回值为打开的结果,如果打开成功返回true、打开失败false。可以通过lastError函数获取错误信息。
bool QSqlDatabase::open()
// 返回上一次的错误信息封装类
QSqlError QSqlDatabase::lastError() const
// 从QSqlError对象中提取错误信息文本
QString QSqlError::text() const
// 返回数据库连接的打开状态
bool QSqlDatabase::isOpen() const
// 关闭数据库连接
void QSqlDatabase::close()
dialog.h
#ifndef DIALOG_H
#define DIALOG_H#include <QDialog>
#include <QButtonGroup>
#include <QSqlDatabase>
#include <QDebug>
#include <QSqlError>
#include <QMessageBox>namespace Ui {
class Dialog;
}class Dialog : public QDialog
{
Q_OBJECTpublic:
explicit Dialog(QWidget *parent = 0);
~Dialog();private:
Ui::Dialog *ui;
QButtonGroup *group;
QSqlDatabase db; // 数据库连接对象
void connetD2B(); // 连接到数据库private slots:
void btnClickedSlots(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(btnClickedSlots(int))); connetD2B();
}Dialog::~Dialog()
{
// 关闭数据库连接
if(db.isOpen())
{
db.close();
}
delete ui;
}// 连接数据库
void Dialog::connetD2B()
{
// 获取数据库的连接对象
db = QSqlDatabase::addDatabase("QSQLITE");
// 设置数据库名称
db.setDatabaseName("book_management.db");
// 打开数据库连接
bool ret = db.open();
if(ret == true)
{
qDebug () << "打开成功";
}
else
{
// 数据库连接打开失败
QSqlError errInfo = db.lastError();
QString text = errInfo.text();
QMessageBox::critical(this,"错误",text);
}
}void Dialog::btnClickedSlots(int id)
{
if(id == 1)
{
qDebug () << "增加";
}
else if(id == 2)
{
qDebug () << "删除";
}
else if(id == 3)
{
qDebug () << "修改";
}
else if(id == 4)
{
qDebug () << "查找";
}
else
{ }
}
3、创建表
建表语句:
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的可视化软件
下载链接:百度网盘 请输入提取码
提取码:hqyj
dialog.h
#ifndef DIALOG_H
#define DIALOG_H#include <QDialog>
#include <QButtonGroup>
#include <QSqlDatabase>
#include <QDebug>
#include <QSqlError>
#include <QMessageBox>
#include <QSqlQuery>private:
void createTable(); // 创建表#endif // DIALOG_H
dialog.cpp
#include "dialog.h"
#include "ui_dialog.h"// 连接数据库
void Dialog::connetD2B()
{
// 获取数据库的连接对象
db = QSqlDatabase::addDatabase("QSQLITE");
// 设置数据库名称
db.setDatabaseName("book_management.db");
// 打开数据库连接
bool ret = db.open();
if(ret == true)
{
qDebug () << "打开成功";
createTable();
}
else
{
// 数据库连接打开失败
QSqlError errInfo = db.lastError();
QString text = errInfo.text();
QMessageBox::critical(this,"错误",text);
}
}// 创建表
void Dialog::createTable()
{
// sql语句
QString sql = "CREATE TABLE book(id INTEGER PRIMARY KEY,name TEXT,price REAL,author TEXT);"; // 创建数据库操作类
QSqlQuery sq; if(sq.exec(sql)) // 表创建成功
{
qDebug() << "建表成功";
}
else // 建表失败,注意:建表成功或者失败都很正常,如果要建立的表已经存在,就会建表失败
{
QSqlError errInfo = sq.lastError();
QString text = errInfo.text();
qDebug() << "建表失败:" << text;
}
}
4、增删改
增删改操作都需要录入用户输入,然后把用户输入的数据组装成SQL语句,最后执行。
组装SQL语句有两种方式:
- 字符串拼接
这种方式原理简单,但是容易出错,且安全性较低。
- 预处理+占位符
推荐使用这种方式,这种方式需要先编写有占位符的预处理SQL语句,交给Qt,Qt内部就知道要执行的SQL语句格式,然后在进行参数与占位符的替换,最终执行。
占位符有两种表示风格:
- Oracle风格
使用:字段的格式
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)
dialog.h
#ifndef DIALOG_H
#define DIALOG_H#include <QDialog>
#include <QButtonGroup>
#include <QSqlDatabase>
#include <QDebug>
#include <QSqlError>
#include <QMessageBox>
#include <QSqlQuery>namespace Ui {
class Dialog;
}class Dialog : public QDialog
{
Q_OBJECT
private:
void insertData(); // 添加数据
};#endif // DIALOG_H
dialog.cpp
#include "dialog.h"
#include "ui_dialog.h"// 插入数据
void Dialog::insertData()
{
QString name = ui->lineEdit->text();
if(name == "")
{
QMessageBox::warning(this,"提示","请输入书名");
return;
}
QString author = ui->lineEdit_2->text();
if(author == "")
{
QMessageBox::warning(this,"提示","请输入作者名称");
return;
} int id = ui->spinBox->value();
double price = ui->doubleSpinBox->value(); // 预处理的SQL语句
QString sql = "INSERT INTO book VALUES(?,?,?,?)"; // 预处理
QSqlQuery sq;
sq.prepare(sql); // 绑定参数
sq.addBindValue(id);
sq.addBindValue(name);
sq.addBindValue(price);
sq.addBindValue(author); // 执行绑定后的SQL语句
if(sq.exec())
{
QMessageBox::information(this,"通知","数据插入成功");
}
else // 失败
{
// 获取错误信息封装类
QSqlError info = sq.lastError();
QString text = info.text();
QMessageBox::warning(this,"通知","数据插入失败");
qDebug() << text;
}
}void Dialog::btnClickedSlots(int id)
{
if(id == 1)
{
qDebug () << "增加";
insertData();
}
else if(id == 2)
{
qDebug () << "删除";
}
else if(id == 3)
{
qDebug () << "修改";
}
else if(id == 4)
{
qDebug () << "查找";
}
else
{ }
}
删除
dialog.h
#ifndef DIALOG_H
#define DIALOG_H#include <QDialog>
#include <QButtonGroup>
#include <QSqlDatabase>
#include <QDebug>
#include <QSqlError>
#include <QMessageBox>
#include <QSqlQuery>class Dialog : public QDialog
{
private:
void deleteData(); // 删除数据
};#endif // DIALOG_H
dialog.cpp
#include "dialog.h"
#include "ui_dialog.h"// 删除数据
void Dialog::deleteData()
{
int id = ui->spinBox->value(); // 查询表中id是否存在
// TODO // 预处理的SQL语句
QString sql = "DELETE FROM book WHERE id=?"; // 预处理
QSqlQuery sq;
sq.prepare(sql); // 绑定参数
sq.addBindValue(id); if(sq.exec())
{
QMessageBox::information(this,"通知","数据删除成功");
}
else
{
// 获取错误信息封装类
QSqlError info = sq.lastError();
QString text = info.text();
QMessageBox::critical(this,"通知",text);
}
}void Dialog::btnClickedSlots(int id)
{
if(id == 1)
{
qDebug () << "增加";
insertData();
}
else if(id == 2)
{
qDebug () << "删除";
deleteData();
}
else if(id == 3)
{
qDebug () << "修改";
}
else if(id == 4)
{
qDebug () << "查找";
}
else
{
}
}
改
// 绑定Oracle风格的占位符参数,绑定的顺序可以乱序
// 参数1:占位符
// 参数2:要绑定的数据
void bindValue(const QString & placeholder, const QVariant & val)
dialog.h
#ifndef DIALOG_H
#define DIALOG_Hclass Dialog : public QDialog
{private:
void updateData(); // 更改数据
};#endif // DIALOG_H
dilaog.cpp
#include "dialog.h"
#include "ui_dialog.h"Dialog::Dialog(QWidget *parent) :
QDialog(parent),
ui(new Ui::Dialog)
{
ui->setupUi(this);
}// 更改数据
void Dialog::updateData()
{
// 获取用户输入
QString name = ui->lineEdit->text();
if(name == "")
{
QMessageBox::warning(this,"提示","请输入书名!");
return;
}
QString author = ui->lineEdit_2->text();
if(author == "")
{
QMessageBox::warning(this,"提示","请输入作者名!");
return;
} int id = ui->spinBox->value();
double price = ui->doubleSpinBox->value(); // 预处理sql语句(Oracle风格)
QString sql = "UPDATE book SET name=:name,price=:price,author=:author WHERE id=:id"; // 预处理
QSqlQuery sq;
sq.prepare(sql); // 绑定数据
sq.bindValue(":price",price);
sq.bindValue(":id",id);
sq.bindValue(":author",author);
sq.bindValue(":name",name); // 执行绑定后的sql语句
if(sq.exec())
{
qDebug() << "更新成功";
QMessageBox::information(this,"提示","数据更改成功");
}
else
{
QString text = sq.lastError().text();
QMessageBox::critical(this,"提示",text);
}}void Dialog::btnClickedSlots(int id)
{
if(id == 1)
{
qDebug () << "增加";
insertData();
}
else if(id == 2)
{
qDebug () << "删除";
deleteData();
}
else if(id == 3)
{
qDebug () << "修改";
updateData();
}
else if(id == 4)
{
qDebug () << "查找";
}
else
{ }
}
5、查询
5.1 全查
相关函数
// 判断查询结果有无数据,如果有则移动游标并取出,没有返回false
bool QSqlQuery::next()
// 按照字段序号取出对应的值,需要从0开始
// 返回值为QVariant类型,可以根据需要直接转为所需类型
QVariant QSqlQuery::value(int index) const
// 按照字段名称取出对应的值
// 返回值为QVariant类型,可以根据需要直接转为所需类型
QVariant QSqlQuery::value(const QString & name) const
dialog.h
#ifndef DIALOG_H
#define DIALOG_H#include <QDialog>
#include <QButtonGroup>
#include <QSqlDatabase>
#include <QDebug>
#include <QSqlError>
#include <QMessageBox>
#include <QSqlQuery>namespace Ui {
class Dialog;
}class Dialog : public QDialog
{
private:
void seleteAll(); // 查找全部数据
bool isDataExists(int id); // 判断数据是否存在
};#endif // DIALOG_H
dilaog.cpp
#include "dialog.h"
#include "ui_dialog.h"// 全查
void Dialog::seleteAll()
{
ui->textBrowser->clear();
QString sql = "SELECT * FROM book";
QSqlQuery sq; if(sq.exec(sql))
{
while(sq.next()) // 循环取出
{
QString id = sq.value(0).toString();
QString name = sq.value(1).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);
}
}
}// 判断数据是否存在,采用字符串拼接的方式
bool Dialog::isDataExists(int id)
{
QString idText = QString::number(id);
QString sql = "SELECT *FROM book WHERE id=";
sql.append(idText); // 拼接只为证明可以使用,但是不建议 QSqlQuery sq;
if(sq.exec(sql))
{
return sq.next();
}
else
{
return false;
}
}void Dialog::btnClickedSlots(int id)
{
if(id == 1)
{
qDebug () << "增加";
insertData();
}
else if(id == 2)
{
qDebug () << "删除";
deleteData();
}
else if(id == 3)
{
qDebug () << "修改";
updateData();
}
else if(id == 4)
{
qDebug () << "查找";
seleteAll();
}
else
{ }
}
5.2 模糊查询
可以使用LIKE关键字配合两个通配符实现模糊查询。
- %
任意多个(0,1,......n)字符
- _
任意一个字符
[查询] 查询“文”字辈的人员信息。
SELECT * FROM book WHERE name LIKE "_文%";
[例子]查询姓名中包含"文"的人员信息
SELECT * FROM book WHERE name LIKE "%文%";
dialog.h
#ifndef DIALOG_H
#define DIALOG_H#include <QDialog>
#include <QButtonGroup>
#include <QSqlDatabase>
#include <QDebug>
#include <QSqlError>
#include <QMessageBox>
#include <QSqlQuery>namespace Ui {
class Dialog;
}class Dialog : public QDialog
{
Q_OBJECTpublic:
explicit Dialog(QWidget *parent = 0);
~Dialog();private:
Ui::Dialog *ui;
QButtonGroup *group;
QSqlDatabase db; // 数据库连接对象
void connetD2B(); // 连接到数据库
void createTable(); // 创建表
void insertData(); // 添加数据
void deleteData(); // 删除数据
void updateData(); // 更改数据
void seleteAll(); // 查找全部数据
bool isDataExists(int id); // 判断数据是否存在
void selectLike(); // 模糊查询private slots:
void btnClickedSlots(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(btnClickedSlots(int))); connetD2B();
}Dialog::~Dialog()
{
// 关闭数据库连接
if(db.isOpen())
{
db.close();
}
delete ui;
}// 连接数据库
void Dialog::connetD2B()
{
// 获取数据库的连接对象
db = QSqlDatabase::addDatabase("QSQLITE");
// 设置数据库名称
db.setDatabaseName("book_management.db");
// 打开数据库连接
bool ret = db.open();
if(ret == true)
{
qDebug () << "打开成功";
createTable();
}
else
{
// 数据库连接打开失败
QSqlError errInfo = db.lastError();
QString text = errInfo.text();
QMessageBox::critical(this,"错误",text);
}
}// 创建表
void Dialog::createTable()
{
// sql语句
QString sql = "CREATE TABLE book(id INTEGER PRIMARY KEY,name TEXT,price REAL,author TEXT);"; // 创建数据库操作类
QSqlQuery sq; if(sq.exec(sql)) // 表创建成功
{
qDebug() << "建表成功";
}
else // 建表失败,注意:建表成功或者失败都很正常,如果要建立的表已经存在,就会建表失败
{
QSqlError errInfo = sq.lastError();
QString text = errInfo.text();
qDebug() << "建表失败:" << text;
}
}// 插入数据
void Dialog::insertData()
{
QString name = ui->lineEdit->text();
if(name == "")
{
QMessageBox::warning(this,"提示","请输入书名");
return;
}
QString author = ui->lineEdit_2->text();
if(author == "")
{
QMessageBox::warning(this,"提示","请输入作者名称");
return;
} int id = ui->spinBox->value();
double price = ui->doubleSpinBox->value(); // 预处理的SQL语句
QString sql = "INSERT INTO book VALUES(?,?,?,?)"; // 预处理
QSqlQuery sq;
sq.prepare(sql); // 绑定参数
sq.addBindValue(id);
sq.addBindValue(name);
sq.addBindValue(price);
sq.addBindValue(author); // 执行绑定后的SQL语句
if(sq.exec())
{
QMessageBox::information(this,"通知","数据插入成功");
}
else // 失败
{
// 获取错误信息封装类
QSqlError info = sq.lastError();
QString text = info.text();
QMessageBox::warning(this,"通知","数据插入失败");
qDebug() << text;
}
}// 删除数据
void Dialog::deleteData()
{
int id = ui->spinBox->value(); // 查询表中id是否存在
if(!isDataExists(id))
{
QMessageBox::information(this,"提示","没有找到要删除的数据");
return;
} // 预处理的SQL语句
QString sql = "DELETE FROM book WHERE id=?"; // 预处理
QSqlQuery sq;
sq.prepare(sql); // 绑定参数
sq.addBindValue(id); if(sq.exec())
{
QMessageBox::information(this,"通知","数据删除成功");
}
else
{
// 获取错误信息封装类
QSqlError info = sq.lastError();
QString text = info.text();
QMessageBox::critical(this,"通知",text);
}
}// 更改数据
void Dialog::updateData()
{
// 获取用户输入
QString name = ui->lineEdit->text();
if(name == "")
{
QMessageBox::warning(this,"提示","请输入书名!");
return;
}
QString author = ui->lineEdit_2->text();
if(author == "")
{
QMessageBox::warning(this,"提示","请输入作者名!");
return;
} int id = ui->spinBox->value();
double price = ui->doubleSpinBox->value(); // 查询表中id是否存在
if(!isDataExists(id))
{
QMessageBox::information(this,"提示","没有找到要修改的数据");
return;
} // 预处理sql语句(Oracle风格)
QString sql = "UPDATE book SET name=:name,price=:price,author=:author WHERE id=:id"; // 预处理
QSqlQuery sq;
sq.prepare(sql); // 绑定数据
sq.bindValue(":price",price);
sq.bindValue(":id",id);
sq.bindValue(":author",author);
sq.bindValue(":name",name); // 执行绑定后的sql语句
if(sq.exec())
{
qDebug() << "更新成功";
QMessageBox::information(this,"提示","数据更改成功");
}
else
{
QString text = sq.lastError().text();
QMessageBox::critical(this,"提示",text);
}}// 全查
void Dialog::seleteAll()
{
ui->textBrowser->clear();
QString sql = "SELECT * FROM book";
QSqlQuery sq; if(sq.exec(sql))
{
while(sq.next()) // 循环取出
{
QString id = sq.value(0).toString();
QString name = sq.value(1).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);
}
}
}// 判断数据是否存在,采用字符串拼接的方式
bool Dialog::isDataExists(int id)
{
QString idText = QString::number(id);
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->lineEdit->text();
if(name == "")
{
QMessageBox::warning(this,"提示","请输入书名");
return;
} QString sql = "SELECT * FROM book WHERE name LIKE ?"; // 预处理
QSqlQuery sq;
sq.prepare(sql);
sq.addBindValue(name.prepend("%").append("%"));
if(sq.exec())
{
// 是否查询到状态
bool retState = true;
// 清空上一次显式
ui->textBrowser->clear(); while(sq.next())
{
QString id = sq.value(0).toString();
QString name = sq.value(1).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);
retState = false;
}
if(retState)
{
QMessageBox::information(this,"提示","没有查询到相关数据");
}
}
else
{
QString text = sq.lastError().text();
text.append("查询失败");
QMessageBox::critical(this,"错误",text);
}
}void Dialog::btnClickedSlots(int id)
{
if(id == 1)
{
qDebug () << "增加";
insertData();
}
else if(id == 2)
{
qDebug () << "删除";
deleteData();
}
else if(id == 3)
{
qDebug () << "修改";
updateData();
}
else if(id == 4)
{
qDebug () << "查找";
selectLike();
}
else
{ }
}