• QT_C++_数据库


    QT_C++_数据库

    一、查询QT支持的数据库类型

    在这里插入图片描述
    1、在.pro文件中加入sql模块
    在这里插入图片描述
    2、查询支持驱动类型

    QStringList drivers = QSqlDatabase::drivers();
    foreach (QString driver, drivers) {
        qDebug() << driver;
    }
    
    //打印信息
    "QSQLITE"
    "QODBC"
    "QODBC3"
    "QPSQL"
    "QPSQL7"
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    二、举例说明数据库的简单用法

    #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
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    #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
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86

    三、下面是分开讲解

    1、QtSql
    要使用QtSql 模块的话,需要在.pro文件中添加这么一句:

    QT += sql 
    
    • 1

    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;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    3、QSqlQuery
    通过exec()成员函数来执行DML(数据操作语言)语句,如CREATE 、SELECT、INSERT、UPDATE和DELETE,以及DDL(数据定义语言)语句等.

    QSqlQuery query;
    query.exec("DROP TABLE students");    //删除名为students的表
    
    • 1
    • 2

    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
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    5、导入数据:

    query.exec("INSERT INTO students (name, score,class) "
                   "VALUES ('小张', 85, '初2-1班')");  
                  //向students表里的(name, score,class)标题下插入一项数据'小张', 85, '初2-1班'
    
    • 1
    • 2
    • 3

    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();               //加入库中
     }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31

    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;
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    还有其它语句,比如:

    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 ");//查询所有内容
    
    • 1
    • 2
    • 3

    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的一行
    
    • 1
    • 2

    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 ");
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    四、数据库数据映射

    说明:把数据库中的数据映射到控件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);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53

    在这里插入图片描述

    五、数据库存储照片(把图片路径存入数据库)

    说明:介绍 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]));
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
  • 相关阅读:
    Springboot毕设项目基于Java的Cisco网络安全设备采购平台wl7jy(java+VUE+Mybatis+Maven+Mysql)
    java项目_第168期ssm二手车交易网站-_计算机毕业设计
    移动端web调试工具vConsole使用详解
    Istio Ambient Mesh 介绍
    C++ 编译报错error: invalid new-expression of abstract class type
    GBase 8c V3.0.0数据类型——访问权限查询函数
    ubuntu22.04编译PBRT-v4
    C陷阱与缺陷 第6章 预处理器 6.4 宏并不是类型定义
    [计算机毕业设计]大数据疫情分析与可视化系统
    Linux —— 软链接和硬链接
  • 原文地址:https://blog.csdn.net/weixin_50183638/article/details/125428072