Qt数据库编程
1.项目文件添加sql 、添加头文件
#include <QsqlDatabase>数据库连接处理 eg:QSqlDatabase db_student
#include <QSqlQuery>连接完成后操作数据库
#include <QSqlError> 打印数据库相关错误
私有成员:
QSqlDatabase db_student; //创建的数据库连接
QString db_file; //数据库的文件名
数据库文件命名 可以通过给定默认参数(db后缀 声明写了默认值,则定义只需要写类型)
比如 explicit Widget(QWidget *parent = 0,QString file_name = "student.db");
Widget::Widget(QWidget *parent,QString file_name) :
QWidget(parent),db_file(file_name),
ui(new Ui::Widget) //数据库文件名为student.db
括号内是给定默认值(这里是把QString xxx给了定义的file_name),冒号后是初始化列表(常给成员变量赋值,这里是把括号内初始化的file_name给了QString类型的数据库文件名db_file -- 后面需要给数据库连接设置这个QString类型的名字)
构造函数:
2.数据库连接db_student = QSqlDatabase::addDatabase("QSQLITE","连接名 ");
2.1声明定义一个QSqlDatabase类的对象,db_student,用来创建连接
2.2连接名qt_sql_default_connection通过使用不同的连接名称,你可以在同一应用程序中管理多个数据库连接。
2.3数据库本地文件名student.db,用来检查数据库文件是否存在,以及本地使用
3.绑定数据库连接对象和数据库名字 打开数据库 检查数据库文件是否存在
3.1db_student.setDatabaseName(db_file);//通过连接绑定数据库本地名
3.2 if(!db_student.open())//通过连接打开数据库 返回布尔值 失败通过db_student.lastError().text()打印
3.3 QFile file(db_file);bool isFileExists = file.exists();//文件操作 判断student.db是否存在于本地
4.操作数据库(如果数据库文件不存在 if (!isFileExists))
QSqlQuery query(db_student); //使用数据库连接对象建表(此处使用连接名query()括号里不写东西则使用上面addDatabase缺省的连接名 我觉得要不写都不写 要写都写 建议都写-add连接时要写连接名,query操作数据库时要写数据库连接对象名)
4.1 写出str并执行query.exec(str) (注意判错) ----如果数据库不存在则执行下列初始值插入操作
创建表: QString str = "create table Student(num varchar(64) primary key, name varchar(128), sex varchar(16), age varchar(16) )"; --表名为Student,完整的指令 ----直接执行完整语句
if(!query.exec(str)){}qDebug()<<str<<"faild";qDebug()<<query.lastError().text();
插入数据1:str = "insert into Student values('2024','zhangsan','boy','18')"; ----直接执行完整语句 常用!
if(!query.exec(str)){} query.lasterror().text();
插入数据2: str = "insert into Student values(?,?,?,?)"; ----待定问号数据依次插入addbindvalue(??--add)
query.prepare(str);//query准备执行str
query.addBindValue("2025"); //双引号 ?和:xx都是占位符
query.addBindValue("mike");
插入数据3: str = "insert into Student values(:xx,:xxx,:sex,:age)"; ----冒号替换式插入bindvalue
query.prepare(str);
query.BindValue(":xx","2026");
query.BindValue(":xxx","xiaoming");
......
if (!query.exec()) //prepare则exec(无参数)
插入数据4:str = "insert into Student values(:num,:name,:sex,:age)"; ----冒号数字替换式插入bindvalue 常用!
query.prepare(str);
query.bindValue(0,"20240105004");
if (!query.exec())
如果数据库文件(.db)不存在,则创建表并插入初始值
5.展示表的函数
调用showInfo();
析构函数:
delete ui;
db_student.close();
6.清除行编辑器、下拉列表框置为-1//0表示第一个选项 1表示第二个选项
写clearInputs函数
void Widget::clearInputs()
{
ui->cb_sex->setCurrentIndex(-1); //下拉列表框函数还需熟悉
ui->le_age->clear();
ui->le_name->clear();
ui->le_num->setText("2024010500");
}
7.写showInfo函数
7.1查找
执行QString str = "select *from Student";
QSqlQuery query(db_student)对象操作数据库 执行query.exec()程序并判错
7.2清空文本编辑框
7.3循环检索
//QList是表格的意思,要加<存储的列表类> QStringList是Qt中用于存储字符串列表的类 Qstring用来处理单个字符串。
QList<QStringList> list;
while(query.next()){ //遍历所有查询到的记录
QStringList record;
for(int i=0;i<4;i++){
record<<query.value(i).toString();
}
list.append(record); //record里面有多个散的QStringList 每个QStringList又包含多个QString
}
//理解:提取每一行的各个字段值,并将这些值存储在一个字符串列表中。然后,这些字符串列表被添加到一个主列表中。小明 男 25 2021 小红 女 21 2020...每一次完整for循环(4次)表示一条数据收集完成
7.3“ 循环检索
ui->te->clear();//显示前清空文本编辑框
while(query.next())//下一条不为空
{
QString tmp;
tmp += query.value(0).toString() + " ";//学号
tmp += query.value(1).toString() + " ";//姓名
tmp += query.value(2).toString() + " ";//性别
tmp += query.value(3).toString(); //年龄
ui->te->append(tmp);
}
8 转到槽函数
8.1新增
void Widget::on_pb_new_clicked()
{
QString str = "insert into Student values(:1,:1,:1,:1)";
QSqlQuery query(db_student);
query.prepared(str);
query.BindValues(0,ui->le_num->text());
query.bindValue(1,ui->le_name->text());
query.bindValue(2,ui->cb_sex->currentText());
query.bindValue(3,ui->le_age->text());
if (!query.exec())//无需放入参数str 因为已经prepare了
{
qDebug()<<str<<"faild";
qDebug()<<query.lastError().text();
return;
}
showInfo();
clearInputs();
}
8.2删除
void Widget::on_pb_delete_clicked()//???
{
QString str = "delete from Student where num=?";//把所有学号为这个的记录都删掉
QSqlQuery query;
query.prepare(str);
query.addBindValue(ui->le_num->text());
if (!query.exec())//无需放入参数str 因为已经prepare了
{
qDebug()<<str<<"faild";
qDebug()<<query.lastError().text();
return;
}
showInfo();
clearInputs();
}
8.3查找
void Widget::on_pb_search_clicked()
{
QString str = "select * from Student where num=?";//把所有学号为这个的记录都删掉
QSqlQuery query;
query.prepare(str);//非完整语句传str参数后,随后调用query.exec(),取!判错
query.addBindValue(ui->le_num->text());
if (!query.exec())//无需放入参数str 因为已经prepare了
{
qDebug()<<str<<"faild";
qDebug()<<query.lastError().text();
return;
}
if(query.first()){
ui->le_name->setText(query.value(1).toString());
ui->cb_sex->setCurrentText(query.value(2).toString());
ui->le_age->setText(query.value(3).toString());
}
}
8.4修改
void Widget::on_pb_search_clicked()
{
QString str = "select * from Student where num=?";//把所有学号为这个的记录都删掉
QSqlQuery query;
query.prepare(str);//非完整语句传str参数后,随后调用query.exec(),取!判错
query.addBindValue(ui->le_num->text());
if (!query.exec())//无需放入参数str 因为已经prepare了
{
qDebug()<<str<<"faild";
qDebug()<<query.lastError().text();
return;
}
if(query.first()){
ui->le_name->setText(query.value(1).toString());
ui->cb_sex->setCurrentText(query.value(2).toString());
ui->le_age->setText(query.value(3).toString());
}
}
例题1 文本编辑框+数据库的增删改查
widget.h:
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include <QSqlDatabase>//数据库连接处理
namespace Ui {
class Widget;
}
class Widget : public QWidget
{
Q_OBJECT
public:
explicit Widget(QWidget *parent = 0,QString file_name = "student.db");//初始化列表
~Widget();
void showInfo();
void clearInputs();
private slots:
void on_pb_new_clicked();
void on_pb_delete_clicked();
void on_pb_search_clicked();
void on_pb_change_clicked();
private:
Ui::Widget *ui;
QSqlDatabase db_student; //创建的数据库连接
QString db_file; //数据库的文件名
};
#endif // WIDGET_H
widget.cpp
#include "widget.h"
#include "ui_widget.h"
#include <QDebug>
#include <QSqlError>//打印错误
#include <QSqlQuery>//连接之后的操作数据库
#include <QFile>
Widget::Widget(QWidget *parent,QString file_name) :
QWidget(parent),db_file(file_name),
ui(new Ui::Widget)
{
ui->setupUi(this);
ui->cb_sex->setFixedWidth(187);
setWindowTitle("数据库-学生信息登记");
QFile file(db_file);
bool isFileExists = file.exists();//判断数据是否存在来决定是否需要建立数据库表
//"QSQLITE"表示使用的数据库类型为sqlite
//不指定数据连接的名字,会使用缺省名:"qt_sql_default_connection"
db_student = QSqlDatabase::addDatabase("QSQLITE");//构造函数可以直接访问私有成员变量吗
qDebug()<<db_student.connectionName();//打印第一个连接的名字
qDebug()<<db_student.connectionNames();//打印所有连接的名字
// //指定数据连接的名字
// QSqlDatabase db_2 = QSqlDatabase::addDatabase("QSQLITE","my_db_connection");
// qDebug()<<db_student.connectionName();
// qDebug()<<db_student.connectionNames();
//设置数据库的文件
//db_student.setDatabaseName(db_file);//设置名字
db_student.setDatabaseName("student.db");//设置名字
//通过连接打开数据库
if(!db_student.open()){
qDebug()<<"数据库打开失败";
qDebug()<<db_student.lastError().text();
}
else{
qDebug()<<"数据库打开成功";
}
if (!isFileExists){
qDebug()<<"数据库文件不存在";
QSqlQuery query(db_student);//使用数据库连接:db_student -- 建表
//等效QSqlQuery query;//不使用 数据库连接,它使用连接名字为 "qt_sql_default_connection"
QString str = "create table Student(num varchar(64) primary key,name varchar(128),sex varchar(16),age varchar(16))";
if (!query.exec(str)){
qDebug()<<str<<"faild";
qDebug()<<query.lastError().text();
}
//插入数据 -- 方法1
str = "insert into Student values('20240105001','小明','男','21')";//不能写成xx='xxxx',
if (!query.exec(str)){
qDebug()<<str<<"faild";
qDebug()<<query.lastError().text();
}
//插入数据 -- 方法2
str = "insert into Student values(?,?,?,?)";//插入待定数据
query.prepare(str);
query.addBindValue("20240105002");
query.addBindValue("麦克");
query.addBindValue("男");
query.addBindValue("20");
if (!query.exec())//无需放入参数str 因为已经prepare了
{
qDebug()<<str<<"faild";
qDebug()<<query.lastError().text();
}
//插入数据 -- 方法3
str = "insert into Student values(:num,:xxx,:sex,:age)";
query.prepare(str);
query.bindValue(":num","20240105015");//替换 03
query.bindValue(":xxx","阿瑟2");
query.bindValue(":sex","男");
query.bindValue(":age","23");
if (!query.exec())//无需放入参数str 因为已经prepare了
{
qDebug()<<str<<"faild";
qDebug()<<query.lastError().text();
}
//插入数据 -- 方法3.1
str = "insert into Student values(:num,:name,:sex,:age)";
query.prepare(str);
query.bindValue(0,"20240105004");//替换
query.bindValue(1,"梅梅");
query.bindValue(2,"女");
query.bindValue(3,"19");
if (!query.exec())//无需放入参数str 因为已经prepare了
{
qDebug()<<str<<"faild";
qDebug()<<query.lastError().text();
}
}
else{
qDebug()<<"数据库文件已存在";
}
//显示数据库里所有记录
showInfo();
}
Widget::~Widget()
{
delete ui;
//关闭数据库 连接
db_student.close();
}
void Widget::clearInputs()
{
ui->cb_sex->setCurrentIndex(-1);
ui->le_age->clear();
ui->le_name->clear();
ui->le_num->setText("2024010500");
}
void Widget::showInfo()
{
QString str = "select * from Student";
QSqlQuery query(db_student);//指定 数据库 连接
if (!query.exec(str))//完整的 要加字串
{
qDebug()<<str<<"faild";
qDebug()<<query.lastError().text();
return;
}
ui->te->clear();//显示前清空文本编辑框
while(query.next())//下一条不为空
{
QString tmp;
tmp += query.value(0).toString() + " ";//学号
tmp += query.value(1).toString() + " ";//姓名
tmp += query.value(2).toString() + " ";//性别
tmp += query.value(3).toString(); //年龄
ui->te->append(tmp);
}
}
void Widget::on_pb_new_clicked()
{
QString str = "insert into Student values(:1,:1,:1,:1)";
QSqlQuery query(db_student);
query.prepare(str);
query.bindValue(0,ui->le_num->text());//替换
query.bindValue(1,ui->le_name->text());
query.bindValue(2,ui->cb_sex->currentText());
query.bindValue(3,ui->le_age->text());
if (!query.exec())//无需放入参数str 因为已经prepare了
{
qDebug()<<str<<"faild";
qDebug()<<query.lastError().text();
return;
}
showInfo();
clearInputs();
}
void Widget::on_pb_delete_clicked()//???
{
QString str = "delete from Student where num=?";//把所有学号为这个的记录都删掉
QSqlQuery query;
query.prepare(str);
query.addBindValue(ui->le_num->text());
if (!query.exec())//无需放入参数str 因为已经prepare了
{
qDebug()<<str<<"faild";
qDebug()<<query.lastError().text();
return;
}
showInfo();
clearInputs();
}
void Widget::on_pb_search_clicked()
{
QString str = "select * from Student where num=?";//把所有学号为这个的记录都删掉
QSqlQuery query;
query.prepare(str);//非完整语句传str参数后,随后调用query.exec(),取!判错
query.addBindValue(ui->le_num->text());
if (!query.exec())//无需放入参数str 因为已经prepare了
{
qDebug()<<str<<"faild";
qDebug()<<query.lastError().text();
return;
}
if(query.first()){
ui->le_name->setText(query.value(1).toString());
ui->cb_sex->setCurrentText(query.value(2).toString());
ui->le_age->setText(query.value(3).toString());
}
}
void Widget::on_pb_change_clicked()
{
QString str = "update Student set name=?,sex=?,age=? where num=?";
QSqlQuery query;
query.prepare(str);
query.addBindValue(ui->le_name->text());
query.addBindValue(ui->cb_sex->currentText());
query.addBindValue(ui->le_age->text());
query.addBindValue(ui->le_num->text());
if (!query.exec())//无需放入参数str 因为已经prepare了
{
qDebug()<<str<<"faild";
qDebug()<<query.lastError().text();
return;
}
showInfo();
clearInputs();
}
演示
例题2 表格(tablewidget)的增删改查
widget.h:
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include <QSqlDatabase>
namespace Ui {
class Widget;
}
class Widget : public QWidget
{
Q_OBJECT
public:
explicit Widget(QString name = "Student.db",QWidget *parent = 0);//默认参数
~Widget();
void showInfo();
private slots:
void on_pb_add_clicked();
void on_pb_update_clicked();
void on_pb_delete_clicked();
private:
Ui::Widget *ui;
QSqlDatabase db_student;
QString db_file;
};
#endif // WIDGET_H
widget.cpp
#include "widget.h"
#include "ui_widget.h"
#include <QFile> //查看表是否存在
#include <QDebug>
#include <QSqlQuery>
#include <QSqlError>
Widget::Widget(QString name,QWidget *parent) ://1.默认参数 和 初始化列表区分开 且默认具体参数只需要写在头文件
QWidget(parent),
ui(new Ui::Widget)
{
ui->setupUi(this);
setWindowTitle("学生信息");
QFile file(db_file);
bool isFileExists = file.exists();//5.判断数据库是否已存在
db_student = QSqlDatabase::addDatabase("QSQLITE");//2.指定数据库类型为"QSQLITE"
db_student.setDatabaseName(db_file);//4.设置数据库文件
//通过连接打开数据库
if(!db_student.open()){
qDebug()<<"数据库打开失败";
qDebug()<<db_student.lastError().text();
}
else{
qDebug()<<"数据库打开成功";
}
if (!isFileExists){
qDebug()<<"数据库文件不存在";
QSqlQuery query(db_student);//使用数据库连接:db_student -- 建表
//等效QSqlQuery query;//不使用 数据库连接,它使用连接名字为 "qt_sql_default_connection"
QString str = "create table Student(num varchar(64) primary key,name varchar(128),sex varchar(16),age varchar(16))";
if (!query.exec(str)){
qDebug()<<str<<"faild";
qDebug()<<query.lastError().text();
}
//插入数据 -- 方法1
str = "insert into Student values('20240105001','小明','男','21')";
if (!query.exec(str)){
qDebug()<<str<<"faild";
qDebug()<<query.lastError().text();
}
//插入数据 -- 方法2???
str = "insert into Student values(?,?,?,?)";//插入待定数据
query.prepare(str);
query.addBindValue("20240105002");
query.addBindValue("麦克");
query.addBindValue("男");
query.addBindValue("20");
if (!query.exec())//无需放入参数str 因为已经prepare了
{
qDebug()<<str<<"faild";
qDebug()<<query.lastError().text();
}
//插入数据 -- 方法3
str = "insert into Student values(:num,:name,:sex,:age)";
query.prepare(str);
query.bindValue(":num","20240105003");//替换
query.bindValue(":name","阿瑟");
query.bindValue(":sex","男");
query.bindValue(":age","23");
if (!query.exec())//无需放入参数str 因为已经prepare了
{
qDebug()<<str<<"faild";
qDebug()<<query.lastError().text();
}
//插入数据 -- 方法3.1
str = "insert into Student values(:num,:name,:sex,:age)";
query.prepare(str);
query.bindValue(0,"20240105004");//替换
query.bindValue(1,"梅梅");
query.bindValue(2,"女");
query.bindValue(3,"19");
if (!query.exec())//无需放入参数str 因为已经prepare了
{
qDebug()<<str<<"faild";
qDebug()<<query.lastError().text();
}
}
else{
qDebug()<<"数据库文件已存在";
}
ui->tw->setColumnCount(4);//设置列数
QStringList list = {"学号","姓名","性别","年龄"};
ui->tw->setHorizontalHeaderLabels(list);//设置label
//显示数据库里所有记录
showInfo();
}
void Widget::showInfo()
{
QString str = "select * from Student";
QSqlQuery query;
if(!query.exec(str)){
qDebug()<<str<<"failed"; //失败
qDebug()<<query.lastError().text();//失败的详细信息
return;
}
QList<QStringList> list; //QList是表的意思 QStringList是Qt中用于存储字符串列表的类。
//list.append(QStringList)
//QString主要用于处理单个字符串,而QStringList主要用于处理字符串列表。在需要处理字符串集合时,使用QStringList会更方便和高效。
while(query.next()){ //遍历所有查询到的记录
QStringList record;
for(int i=0;i<4;i++){
record<<query.value(i).toString();
}
list.append(record);
}
//设置tablewidget的行数
ui->tw->setRowCount(list.size()); //row行数 column列数
for(int i=0;i<list.size();i++){
for(int j=0;j<list.at(i).size();j++){ //list.at(i).size()i行的列数
QTableWidgetItem *item = new QTableWidgetItem(list.at(i).at(j));
ui->tw->setItem(i,j,item);
}
QTableWidgetItem *item = ui->tw->item(i,0);
item->setFlags(item->flags() &~Qt::ItemIsEditable);//设置第一列学号不能修改
}
}
Widget::~Widget()
{
delete ui;
db_student.close();//3.析构函数关闭数据库
}
void Widget::on_pb_add_clicked()
{
if (ui->pb_add->text() == "新增"){
//直接获得当前总行数
int rowNum = ui->tw->rowCount();
ui->tw->insertRow(rowNum);//在最后一行的后面增加空白行
ui->pb_add->setText("提交");
ui->pb_delete->setEnabled(false);//提交时,另外两个按钮灰掉
ui->pb_update->setEnabled(false);
}
else{
int rowNum = ui->tw->rowCount();
rowNum--;//因为是0 base(0行开始算),所以要--
QString str = "insert into Student values(?,?,?,?)";
QSqlQuery query;
query.prepare(str);
query.addBindValue(ui->tw->item(rowNum,0)->data(0).toString());//学号num
query.addBindValue(ui->tw->item(rowNum,1)->data(0).toString());//姓名
query.addBindValue(ui->tw->item(rowNum,2)->data(0).toString());//性别
query.addBindValue(ui->tw->item(rowNum,3)->data(0).toString());//年龄
if(!query.exec()){//prepare后已经绑定 就不需要exec(str)
qDebug()<<str<<"failed"; //失败
qDebug()<<query.lastError().text();//失败的详细信息
return;
}
ui->pb_add->setText("新增");
ui->pb_delete->setEnabled(true);
ui->pb_update->setEnabled(true);
showInfo();
}
}
void Widget::on_pb_update_clicked()
{
int currentRow = ui->tw->currentRow();
qDebug()<<"currentRow = "<<currentRow;
QString str = "update Student set name=?,sex=?,age=? where num=?";
QSqlQuery query;
query.prepare(str);//不是完整语句 要prepare绑定
query.addBindValue(ui->tw->item(currentRow,1)->data(0).toString());//name //获取单元格数据
query.addBindValue(ui->tw->item(currentRow,2)->data(0).toString());//sex
query.addBindValue(ui->tw->item(currentRow,3)->data(0).toString());//age
query.addBindValue(ui->tw->item(currentRow,0)->data(0).toString());//num
if(!query.exec()){//prepare后已经绑定 就不需要exec(str)
qDebug()<<str<<"failed"; //失败
qDebug()<<query.lastError().text();//失败的详细信息
return;
}
showInfo();
}
void Widget::on_pb_delete_clicked() //选中一行 删除
{
int currentRow = ui->tw->currentRow();
qDebug()<<"currentRow = "<<currentRow;
QString str = "delete from Student where num=?";
QSqlQuery query;
query.prepare(str);//不是完整语句 要prepare绑定
query.addBindValue(ui->tw->item(currentRow,0)->data(0).toString());//data一般固定填0
if(!query.exec()){//prepare后已经绑定 就不需要exec(str)
qDebug()<<str<<"failed"; //失败
qDebug()<<query.lastError().text();//失败的详细信息
return;
}
showInfo();
}
演示
Qt数据库显示软件
SQLiteExpertPers
终于写完啦!享受周末了
想做个C++Qt贪吃蛇项目 最近也有个Qt项目 有的忙了嘿嘿