QT_C++_数据库
一、查询QT支持的数据库类型
1、在.pro文件中加入sql模块
2、查询支持驱动类型
QStringList drivers = QSqlDatabase::drivers();
foreach (QString driver, drivers) {
qDebug() << driver;
}
//打印信息
"QSQLITE"
"QODBC"
"QODBC3"
"QPSQL"
"QPSQL7"
二、举例说明数据库的简单用法
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QSqlDatabase>
#include <QDebug>
#include <QStringList>
#include <QSqlError>
#include <QSqlQuery>
#include <QApplication>
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
private:
/* 数据库连接类 */
QSqlDatabase sqlDatabase;
};
#endif // MAINWINDOW_H
#include "mainwindow.h"
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{
/* 设置主窗体的显示位置与大小 */
this->setGeometry(0, 0, 800, 480);
/*打印平台支持的数据库*/
QStringList drivers = QSqlDatabase::drivers();
foreach (QString driver, drivers) {
qDebug() << driver;
}
/* 以QSQLITE驱动方式打开或者创建数据库 */
sqlDatabase = QSqlDatabase::addDatabase("QSQLITE");
sqlDatabase.setDatabaseName("employee.db");
/* 以open的方式打开employee.db数据库,则会创建一个employee.db */
if (!sqlDatabase.open()) {
qDebug() << "连接数据库错误" << sqlDatabase.lastError() << endl;
} else {
qDebug() << "连接数据库成功" << endl;
}
QSqlQuery query;
/* 使用指令式创建表 */
query.exec("create table employee (id int primary key, name vchar(10), "
"age int, sex vchar(3), photo text)");
QStringList photoPath;
/* 当前可执行程序的路径 */
QString path(QApplication::applicationDirPath());
photoPath << path + "/photos/啊万.jpg" << path + "/photos/啊棠.jpg";
/* 以指令的方式插入数据,如果数据已经存在则不会成功不能插入 */
query.exec(tr("insert into employee values(1, '啊万', 27, '男', '%1')").arg(photoPath[0]));
query.exec(tr("insert into employee values(2, '啊棠', 28, '男', '%1')").arg(photoPath[1]));
query.exec(tr("insert into employee values(3, '啊棠1', 29, '男', '%1')").arg(photoPath[1]));
query.exec(tr("insert into employee values(4, '啊棠3', 30, '男', '%1')").arg(photoPath[1]));
/*查询数据库*/
//query.exec("select * from employee where age == 29"); //匹配年纪为29
//query.exec("select * from employee where name glob '*棠'"); //glob表示通配符
query.exec("select * from employee"); //查詢所有
while (query.next()) {
QString id = query.value(0).toString();
QString name = query.value(1).toString();
QString age = query.value(2).toString();
QString sex = query.value(3).toString();
QString photo = query.value(4).toString();
qDebug() << id << name << age << sex << photo;
}
/*删除数据库*/
query.exec("delete from employee where age == 29"); //删除年纪为29的这一行
//query.exec("drop table employee"); //用来删除整表,并且连表结构也会删除,删除后则只能重新创建表
//query.exec("delete from employee"); //删除students表里所有内容
/*修改数据库*/
//query.exec("alter table employee rename to new_employee"); //重命名表,或者在已有的表中添加新的一列
query.exec("alter table employee add column number int"); //新增加一列number,类型是int
query.exec("update employee set number = 120"); //修改number所在的列内容
query.exec("update employee set number=100 where age<28 "); //修改在年纪小于28和大于等于29时,number的值
query.exec("update employee set number=90 where age>=29 ");
query.exec("update employee set number=110 where id=2 "); //修改id为2时候,number的值
query.exec("select * from employee"); //查询所有
while (query.next()) {
QString id = query.value(0).toString();
QString name = query.value(1).toString();
QString age = query.value(2).toString();
QString sex = query.value(3).toString();
QString photo = query.value(4).toString();
QString number = query.value(5).toString();
qDebug() << id << name << age << sex << photo << number;
}
}
MainWindow::~MainWindow()
{
/* 关闭数据库 */
sqlDatabase.close();
qDebug() << "关闭数据库";
}
三、下面是分开讲解
1、QtSql
要使用QtSql 模块的话,需要在.pro文件中添加这么一句:
QT += sql
2、QSqlDatabase
QSqlDatabase类提供了一个接口,用于通过连接访问数据。QSqlDatabase的一个实例表示连接。该连接通过受支持的数据库驱动程序之一提供对数据库的访问,该驱动程序派生自QSqlDriver。
QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");
db.setDatabaseName(QApplication::applicationDirPath()+"/scooters.db"); //如果本目录下没有该文件,则会在本目录下生成,否则连接该文件
if (!db.open()) {
QMessageBox::warning(0, QObject::tr("Database Error"),
db.lastError().text());
return false;
}
3、QSqlQuery
通过exec()成员函数来执行DML(数据操作语言)语句,如CREATE 、SELECT、INSERT、UPDATE和DELETE,以及DDL(数据定义语言)语句等.
QSqlQuery query;
query.exec("DROP TABLE students"); //删除名为students的表
4、创建表:
" PRIMARY KEY AUTOINCREMENT,":表示该列为整数递增,如果为空时则自动填入1,然后在下面的每一行都会自动+1, PRIMARY KEY则表示该列作为列表的主键,通过它可以轻易地获取某一行数据
" INTEGER ":表示该列为带符号的整数
" VARCHAR(40) ":表示该列为可变长字符串,默认只能存储英文和数字或者utf-8,最多存储40个字节.
"NOT NULL ":表示该列的内容不为空
query.exec("CREATE TABLE students ("
"id INTEGER PRIMARY KEY AUTOINCREMENT, "
"name VARCHAR(40) NOT NULL, "
" score INTEGER NOT NULL, "
"class VARCHAR(40) NOT NULL)");
//创建一个students表,标题分别为id、name、score、class
5、导入数据:
query.exec("INSERT INTO students (name, score,class) "
"VALUES ('小张', 85, '初2-1班')");
//向students表里的(name, score,class)标题下插入一项数据'小张', 85, '初2-1班'
6、批量导入库
QStringList names;
names<<"小A"<<"小B"<<"小C"<<"小D"<<"小E"<<"小F"<<"小G"
<<"小H"<<"小I"<<"小G"<<"小K"<<"小L"<<"小M"<<"小N";
QStringList clases;
clases<<"初1-1班"<<"初1-2班"<<"初1-3班"<<"初2-1班"
<<"初2-2班"<<"初2-3班"<<"初3-1班"<<"初3-2班"<<"初3-3班";
QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");
db.setDatabaseName(QApplication::applicationDirPath()+"/scooters.db"); //在本目录下生成
QSqlQuery query;
query.exec("DROP TABLE students"); //先清空一下表
query.exec("CREATE TABLE students ("
"id INTEGER PRIMARY KEY AUTOINCREMENT, "
"name VARCHAR(40) NOT NULL, "
" score INTEGER NOT NULL, "
"class VARCHAR(40) NOT NULL)");
//创建一个students表
query.prepare("INSERT INTO students (name, score,class) "
"VALUES (:name, :score, :class)");
//为每一列标题添加绑定值
foreach (QString name, names) //从names表里获取每个名字
{
query.bindValue(":name", name); //向绑定值里加入名字
query.bindValue(":score", (qrand() % 101)); //成绩
query.bindValue(":class", clases[qrand()%clases.length()] ); //班级
query.exec(); //加入库中
}
7、查询表内容
需要使用WHERE 关键字实现
示例-查询成绩值为60~80之间的学生:
query.exec("SELECT * FROM students WHERE score >= 60 AND score <= 80;");
while(query.next())
{
QString id = query.value(0).toString();
QString name = query.value(1).toString();
QString score = query.value(2).toString();
QString classs = query.value(3).toString();
qDebug()<<id<<name<<score<<classs;
}
还有其它语句,比如:
query.exec("SELECT * FROM students WHERE score >= 80 OR class == '初3-3班'"}//判断成绩大于等于80,或者班级为初3-3班的
query.exec("SELECT * FROM students WHERE class GLOB '*3-3*'"}// GLOB表示通配符,匹配班级带有"3-3"的名字
query.exec("SELECT * FROM students ");//查询所有内容
8、删表内容
DROP: 用来删除整表,并且连表结构也会删除,删除后则只能使用CREATE TABLE来重新创建表
TRUNCATE: 在SQLite中没有该语句,在MySQL中有该语句,用来清楚表内数据,但是表结构不会删除.
DELETE: 删除部分记录,并且表结构不会删除,删除的速度比上面两个语句慢,可以配合WHERE来删除指定的某行
query.exec("DELETE FROM students");//删除students表里所有内容
query.exec("DELETE FROM students WHERE id = 3");//删除id=3的一行
9、改表内容
UPDATE : 用来修改表中内容,可以通过WHERE语句来指定修改
ALTER TABLE: 用来重命名表,或者在已有的表中添加新的一列
query.exec("ALTER TABLE students RENAME TO new_students"); //将students重命名为new_students
query.exec("ALTER TABLE new_students ADD COLUMN 结果 VARCHAR(10)");//向 new_students表里添加新的一列,标题为结果,内容格式为VARCHAR
query.exec("UPDATE new_students SET score = 100 , name = '小A'");//不使用WHERE,直接修改某列吗,修改score和name所在的列内容
/*******使用WHERE,判断小于60的设为不合格,否则设为合格**********/
query.exec("UPDATE new_students SET 结果='不合格' WHERE score<60 ");
query.exec("UPDATE new_students SET 结果='合格' WHERE score>=60 ");
四、数据库数据映射
说明:把数据库中的数据映射到控件QTableView,可以在界面直观展示数据库中的数据,并且在界面中修改了数据后,数据库可以同步改变
/* 以QSQLITE驱动方式打开或者创建数据库 */
sqlDatabase = QSqlDatabase::addDatabase("QSQLITE");
sqlDatabase.setDatabaseName("employee.db");
/* 以open的方式打开employee.db数据库,则会创建一个employee.db */
if (!sqlDatabase.open()) {
qDebug() << "连接数据库错误" << sqlDatabase.lastError() << endl;
} else {
qDebug() << "连接数据库成功" << endl;
}
QSqlQuery query(sqlDatabase);
/* 使用指令式创建表 */
query.exec("create table employee (id int primary key, name vchar(10), "
"age int, sex vchar(3), photo text)");
QStringList photoPath;
/* 当前可执行程序的路径 */
QString path(QApplication::applicationDirPath());
photoPath << path + "/photos/啊万.jpg" << path + "/photos/啊棠.jpg";
/* 以指令的方式插入数据,如果数据已经存在则不会成功不能插入 */
query.exec(tr("insert into employee values(1, '啊万', 27, '男', '%1')").arg(photoPath[0]));
query.exec(tr("insert into employee values(2, '啊棠', 28, '男', '%1')").arg(photoPath[1]));
/* 初始化表格模型 */
QSqlTableModel *model = new QSqlTableModel(this, sqlDatabase);
/* 设置要选中的表格名称 */
model->setTable("employee");
/* 如果有修改则同步修改到数据库,
* 注意这个规则需要与tabview这样的控件才生效,
* 因为tabview可以直接编辑表里的内容 */
model->setEditStrategy(QSqlTableModel::OnFieldChange);
/* 成功则返回true,查看数据库里是否有employee这个表格 */
model->select();
/* 设置表格的头信息,若不设置则显示数据库里的英文字段头信息 */
model->setHeaderData(model->fieldIndex("id"),
Qt::Horizontal, tr("编号"));
model->setHeaderData(model->fieldIndex("name"),
Qt::Horizontal, tr("姓名"));
model->setHeaderData(model->fieldIndex("age"),
Qt::Horizontal, tr("年龄"));
model->setHeaderData(model->fieldIndex("sex"),
Qt::Horizontal, tr("性别"));
QTableView *view = new QTableView;
/* 设置表格的模型为model */
view->setModel(model);
/* 不显示图片路径信息行 */
view->hideColumn(4);
/* 表格居中 */
setCentralWidget(view);
五、数据库存储照片(把图片路径存入数据库)
说明:介绍 Qt 如何使用数据库存储照片的信息。我们知道数据库类型有个 BLOB 数据类型可以用于存储照片信息。但
是本例并不那样做,当数据库数据很多时,将照片(二进制数据)存储到数据库里就不是一个明智的选择了。大字段数据会加重数据库的负担,拖慢数据库,数据库文件越小访问肯定越快,数据库也不用遍历那么多内容,或者加载那么大的数据到内存里,造成响应不及时等。计算机可能处理速度很快,但是对于普通的单核和多核 ARM 开发板来说速度可能会跟不上啊!所以数据库最好是存储照片的路径。照片路径属于字符串文本,不会占用太多空间。
QSqlQuery query(sqlDatabase);
/* 使用指令式创建表 */
query.exec("create table employee (id int primary key, name vchar(10), "
"age int, sex vchar(3), photo text)");
QStringList photoPath;
/* 当前可执行程序的路径 */
QString path(QApplication::applicationDirPath());
photoPath << path + "/photos/啊万.jpg" << path + "/photos/啊棠.jpg";
/* 以指令的方式插入数据,如果数据已经存在则不会成功不能插入 */
query.exec(tr("insert into employee values(1, '啊万', 27, '男', '%1')").arg(photoPath[0]));
query.exec(tr("insert into employee values(2, '啊棠', 28, '男', '%1')").arg(photoPath[1]));
六、实战总结
说明:在我们实际做项目的时候,会将一些用户的设置参数进行保存,类似于单片机的掉电不丢失,单片机是保存在EEPROM,我们的linux项目则是保存在数据库中
/* 数据库连接类 */
QSqlDatabase sqlDatabase;
/* 以QSQLITE驱动方式打开或者创建数据库 */
sqlDatabase = QSqlDatabase::addDatabase("QSQLITE");
sqlDatabase.setDatabaseName("employee.db");
/* 以open的方式打开employee.db数据库,则会创建一个employee.db */
if (!sqlDatabase.open()) {
qDebug() << "连接数据库错误" << sqlDatabase.lastError() << endl;
} else {
qDebug() << "连接数据库成功" << endl;
}
QSqlQuery query;
/* 使用指令式创建表 */
query.exec("create table employee (id int primary key, name vchar(10), "
"age int, sex vchar(3))");
/* 以指令的方式插入数据,如果数据已经存在则不会成功不能插入 */
query.exec("insert into employee values(1, '啊万', 27, '男')");
query.exec("select * from employee"); //查询所有
//query.exec("select * from employee where age == 27");
//query.exec("select name from employee where age == 29");
QSqlRecord rec = query.record();
while (query.next()) { //打印结果如下图
rec = query.record();
int id = rec.indexOf("id");
int name = rec.indexOf("name");
int age = rec.indexOf("age");
int sex = rec.indexOf("sex");
QString id_str = query.value(id).toString();
QString name_str = query.value(name).toString();
QString age_str = query.value(age).toString();
QString sex_str = query.value(sex).toString();
qDebug() << id_str << name_str << age_str << sex_str;
}
sqlDatabase.close();