Qt之数据库使用示例

代码学习

//-----------------------------------连接数据库-----------------------------------

cpp 复制代码
{
    //数据库用的是qsqlite,一个轻型数据库
    QSqlDatabase m_database = new QSqlDatabase(QSqlDatabase::addDatabase("QSQLITE"));
    QString name = QApplication::applicationDirPath() + "/config/WorkingData.db";
    m_database->setDatabaseName(name);//设置数据库名称
    if (!m_database->open())//打开数据库
    {
        XVLog::Instance()->writeError("数据库错误:" + m_database->lastError().text());
        XVLog::Instance()->writeInfo("数据库名称:" + name);
        QMessageBox::critical(this, "警告", "数据库打开失败!!");
        return;
    }
}

//-----------------------------------创建数据库-----------------------------------

cpp 复制代码
{
   if (!m_database->isOpen())//判断数据库是否打开
    {
        QMessageBox::critical(this, "警告", "创建表时数据库未打开!!");
        return;
    }

    qDebug() << "Database is open?" << m_database->isOpen();  // 应为 true
    qDebug() << "Last error:" << m_database->lastError().text();  // 检查错误
    qDebug() << "Available drivers:" << QSqlDatabase::drivers(); //查看所有可用的数据库驱动类型

    // 获取当前日期
    QDate currentDate = QDate::currentDate();
    tableName = "table_" + currentDate.toString("yyyyMMdd");

    // 创建数据表
    QSqlQuery query(*m_database);
    //"CREATE TABLE IF NOT EXISTS " + tableName注释:如果tableName的数据表不存在就创建名称为tableName的数据表
    //id INTEGER PRIMARY KEY AUTOINCREMENT注释: 定义了一个自增主键字段,每插入一条记录会自动递增
    QString createTableSQL = "CREATE TABLE IF NOT EXISTS " + tableName +  
                             " (id INTEGER PRIMARY KEY AUTOINCREMENT, "
                             "time TEXT NOT NULL, "
                             "camera INTEGER NOT NULL, "
                             "offsetXA1 REAL, "
                             "offsetYA1 REAL, "
                             "offsetRA1 REAL, "
                             "DropXA1 REAL, "
                             "DropYA1 REAL, "
                             "DropRA1 REAL, "
                             "ResA1 TEXT, "
                             "offsetXA2 REAL, "
                             "offsetYA2 REAL, "
                             "offsetRA2 REAL, "
                             "DropXA2 REAL, "
                             "DropYA2 REAL, "
                             "DropRA2 REAL, "
                             "ResA2 TEXT)";
    qDebug() << createTableSQL;

    if (!query.exec(createTableSQL))//执行创建数据表
    {
        QMessageBox::critical(this, "警告", "数据表创建失败!!");
        qDebug() << "Last error:" << m_database->lastError().text();
        return;
    }

    if (m_database->tables().contains(tableName))//判断数据库的表中是否存在刚刚创建的数据表
    {
        XVLog::Instance()->writeInfo("数据表已成功创建");
    }
    else
    {
        XVLog::Instance()->writeError("数据表不存在于数据库中!!");
    }
}

//-----------------------------------每7天一个周期清空一下数据表---------------------

cpp 复制代码
{
    //检查表数量
    QSqlQuery query(*m_database);
    //SELECT count(*) FROM sqlite_master WHERE type='table' AND name NOT LIKE 'sqlite_%'‌语句详解:
    //SELECT count(*):这是一个聚合函数,用于统计满足条件的记录总数
    //FROM sqlite_master:sqlite_master 是SQLite的系统表,它存储了数据库中所有表、索引、视图和触发器的信息
    //WHERE type='table':这是一个过滤条件,指定只统计类型为 'table'(即数据表)的记录
    //AND name NOT LIKE 'sqlite_%':这是另一个过滤条件,它使用 NOT LIKE 操作符和通配符 % 来排除所有以 'sqlite_' 开头的表名。在SQLite中,系统表(如 sqlite_master)和某些内部使用的表会以此前缀命名
    //综合来看‌,这条语句的作用是从 sqlite_master 系统表中,找出所有类型为普通数据表('table')并且表名不以 'sqlite_' 开头的记录,并计算其总数
    if (!query.exec(
            "SELECT count(*) FROM sqlite_master WHERE type='table' AND name NOT LIKE 'sqlite_%'"))
    {
        QMessageBox::critical(this, "警告", "数据库中表的数量统计失败!!");
        XVLog::Instance()->writeError("错误信息为:" + query.lastError().text());
        return;
    }

    int tableCount = 0;
    if (query.next())
    {
        tableCount = query.value(0).toInt();
        XVLog::Instance()->writeInfo("当前数据表总数为:" + QString::number(tableCount));

        //如果正好有7张表,清空数据库
        if (tableCount == 7)
        {
            m_database->transaction();  // 开启事务(保证原子性)

            // 获取所有表名
            std::vector<QString> Alltables;
            //用于查询SQLite数据库中所有用户自定义表的名称
            query.exec(
                "SELECT name FROM sqlite_master WHERE type='table' AND name NOT LIKE 'sqlite_%'");
            while (query.next())
            {
                QString tableName = query.value(0).toString();
                Alltables.push_back(tableName);
            }

            qDebug() << "获取到的表格名称数量:" << Alltables.size();

            for (int i = 0; i < Alltables.size(); i++)
            {
                QSqlQuery dropQuery(*m_database);
	//SQL删除表语句,下面代码通常出现在循环结构中,用于批量删除多个数据库表
                if (!dropQuery.exec(QString("DROP TABLE IF EXISTS %1").arg(Alltables.at(i))))
                {
                    qWarning() << "Failed to drop table" << Alltables.at(i) << ":"
                               << dropQuery.lastError().text();
                    m_database->rollback();  // 回滚事务,如果失败保证数据库的完整性,要么全删要么全部留下
                    return;
                }
            }

            m_database->commit();  // 提交事务
            XVLog::Instance()->writeInfo("数据表清除成功.");
        }
    }
}

//-----------------------------------写入数据-----------------------------------

cpp 复制代码
{
    //绑定连接,并写入指令
    QSqlQuery query(*m_database);
    query.prepare("INSERT INTO " + tableName +
                  " (time, camera, offsetXA1, offsetYA1, "
                  "offsetRA1,DropXA1,DropYA1,DropRA1,ResA1,offsetXA2, offsetYA2, "
                  "offsetRA2,DropXA2,DropYA2,DropRA2,ResA2) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, "
                  "?, ?, ?, ?, ?, "
                  "?)");
    query.addBindValue(time);
    query.addBindValue(index);
    query.addBindValue(offsetx_1);
    query.addBindValue(offsety_1);
    query.addBindValue(offsetr_1);
    query.addBindValue(dropx_1);
    query.addBindValue(dropy_1);
    query.addBindValue(dropr_1);
    query.addBindValue(res_a1);
    query.addBindValue(offsetx_2);
    query.addBindValue(offsety_2);
    query.addBindValue(offsetr_2);
    query.addBindValue(dropx_2);
    query.addBindValue(dropy_2);
    query.addBindValue(dropr_2);
    query.addBindValue(res_a2);

    bool result = query.exec();
}

//-----------------------------------读取数据-----------------------------------

cpp 复制代码
{
    QSqlQuery query(*m_database);
    query.exec(
        "SELECT time, camera, offsetXA1, offsetYA1, "
        "offsetRA1,DropXA1,DropYA1,DropRA1,ResA1,offsetXA2, offsetYA2, "
        "offsetRA2,DropXA2,DropYA2,DropRA2,ResA2 FROM " +
        tableName);

    while (query.next())  // 逐行读取结果
    {
        QString time = query.value("time").toString();
        int index = query.value(1).toInt();
        float oxa1 = query.value(2).toFloat();
        float oya1 = query.value(3).toFloat();
        float ora1 = query.value(4).toFloat();
        float dxa1 = query.value(5).toFloat();
        float dya1 = query.value(6).toFloat();
        float dra1 = query.value(7).toFloat();
        QString ra1 = query.value("ResA1").toString();
        float oxa2 = query.value(9).toFloat();
        float oya2 = query.value(10).toFloat();
        float ora2 = query.value(11).toFloat();
        float dxa2 = query.value(12).toFloat();
        float dya2 = query.value(13).toFloat();
        float dra2 = query.value(14).toFloat();
        QString ra2 = query.value("ResA2").toString();
        qDebug() << "时间" << time;
        qDebug() << "工位" << index << "A1首次x偏移:" << oxa1;
        qDebug() << "工位" << index << "A1首次y偏移:" << oya1;
        qDebug() << "工位" << index << "A1首次r偏移:" << ora1;
        qDebug() << "工位" << index << "A1最后x偏移:" << dxa1;
        qDebug() << "工位" << index << "A1最后y偏移:" << dya1;
        qDebug() << "工位" << index << "A1最后r偏移:" << dra1;
        qDebug() << "工位" << index << "A1结果:" << ra1;
        qDebug() << "工位" << index << "A2首次x偏移:" << oxa2;
        qDebug() << "工位" << index << "A2首次y偏移:" << oya2;
        qDebug() << "工位" << index << "A2首次r偏移:" << ora2;
        qDebug() << "工位" << index << "A2最后x偏移:" << dxa2;
        qDebug() << "工位" << index << "A2最后y偏移:" << dya2;
        qDebug() << "工位" << index << "A2最后r偏移:" << dra2;
        qDebug() << "工位" << index << "A2结果:" << ra2;
    }
}
相关推荐
q***42821 小时前
Redis 设置密码(配置文件、docker容器、命令行3种场景)
数据库·redis·docker
运维行者_2 小时前
网站出现 525 错误(SSL 握手失败)修复指南
服务器·网络·数据库·redis·网络协议·bootstrap·ssl
fruge2 小时前
openGauss数据库实操过程:从环境搭建到连接配置,第三方软件进行数据库管理
数据库·oracle
5***79002 小时前
后端服务监控面板,关键业务指标
数据库
Jonathan Star4 小时前
JSON-RPC 2.0 详解
qt·rpc·json
倔强的石头_4 小时前
面向电力生产调度系统的数据库实践:从时序处理到多中心容灾
数据库
q***47184 小时前
MySQL 篇 - Java 连接 MySQL 数据库并实现数据交互
java·数据库·mysql
杨云龙UP4 小时前
【MySQL逻辑备份】基于mysqldump的MySQL 8.0全量逻辑备份脚本
linux·运维·数据库·sql·mysql·mssql
一只爱学习的小鱼儿5 小时前
QT中3D的使用
开发语言·数据库·qt