• 关于Qt数据库开发的一些冷知识


    一、知识要点

    • Qt即支持库的形式直接和数据库通信,也支持ODBC数据源的形式和各种数据库通信,这样就涵盖了所有的情况。
    • Qt数据库程序打包发布,所有前提:注意区分32/64位,你的程序是32位的就必须带上32位的库,64位的必须带上64位的库,这点Qt的库也是这个要求。mysql发布最简单,带上一个mysql的动态库文件就行(windows上的是libmysql.dll),非常简单。sqlserver不用带,因为是微软的亲儿子,一般操作系统自带。postgres需要带上libpq.dll、libintl-8.dll、libiconv-2.dll、libeay32.dll、ssleay32.dll这几个文件就行。oracle需要带上oci.dll、oraociei11.dll(这个文件很大有130MB+),如果不行建议直接安装个oracle client客户端软件,然后对应bin目录设置到环境变量就好。
    • 打包发布后测试下来,发现32位的程序也可以正常连接64位的mysql,64位的程序也可以正常连接32位的mysql,因此判断只要和程序的库的位数一致就行(编译的时候也是这个规则,32位的Qt程序编译数据库插件也要用32位的数据库链接库。),不需要和具体的数据库的位数一致,测试过mysql、sqlserver、postgresql数据库都是类似规则。
    • 大量测试对比下来,通过odbc数据源的方式和直连数据库的方式批量插入大量数据记录,直连方式速度更快,约5%左右,所以建议尽量采用此方式,是在没有此方式的环境才采用odbc数据源的方式,Qt默认自带odbc数据库插件。
    • mysql、postgresql数据库在执行sql脚本的时候,会自动将表名和字段名全部转成小写,oracle全部转成大写,这就导致使用QSqlTableModel调用setTable设置数据库表名的时候,一定要和数据库中的表名一致,区分大小写,mysql数据库默认配置设置的不区分大小写所以没有这个问题,所以就是在对postgresql和oracle数据库的时候一定要注意,本人就是在这里卡了很久,差点要把这巨大的屎盆扣在Qt的BUG上。
    void DbHelper::bindTable(const QString &dbType, QSqlTableModel *model, const QString &table)
    {
        //postgresql全部小写,oracle全部大写,这两个数据库严格区分表名字段名的大小写卧槽
        QString flag = dbType.toUpper();
        if (flag == "POSTGRESQL") {
            model->setTable(table.toLower());
        } else if (flag == "ORACLE") {
            model->setTable(table.toUpper());
        } else {
            model->setTable(table);
        }
    }
    
    • Qt支持不指定数据库名打开数据库,因为有时候是要在连接数据库服务器后,执行sql语句创建数据库。数据库都还没存在怎么连接呢,测试发现sqlite、mysql、sqlserver、postgresql都支持这个特性。在删除和创建数据库的前提是该数据库没有被其他程序占用,比如其他程序已经打开了该数据库则会执行失败。这里我就折磨过很多次,为什么执行失败呢?后面发现第三方数据库工具已经打开了该数据库,把工具关掉就ok了。
    QSqlDatabase database = QSqlDatabase::addDatabase("QMYSQL");
    //database.setDatabaseName("dbtool");
    database.setHostName("127.0.0.1");
    database.setPort(3306);
    database.setUserName("root");
    database.setPassword("root");
    
    if (database.open()) {
        QSqlQuery query(database);
        qDebug() << "删除数据库" << query.exec("drop database dbtool");
        qDebug() << "创建数据库" << query.exec("create database dbtool");
        if (query.exec("select * from userinfo")) {
            while (query.next()) {
                qDebug() << "查询数据库" << query.value(0);
            }
        }
    } else {
         qDebug() << "打开数据库" << database.lastError().text();
    }
    
    • 用QSqlQueryModel+QTableView显示数据,int类型的数据,如果超过100万,会变成科学计数显示,这就很恼火了,肯定不是自己想要的结果。找遍网络搜索,终于找到一个同样问题的哥们,需要对这一列加个空的委托就行。后面发现空委托也不行,超过1000万条又屌样了,需要终极大法重载数据模型显示。
    ui->tableView->setItemDelegateForColumn(0, new QItemDelegate);
    
    //下面是终极大法
    QVariant SqlQueryModel::data(const QModelIndex &index, int role) const
    {
        QVariant value = QSqlQueryModel::data(index, role);
        //超过100万的数值会被科学计数显示需要这里转成字符串显示
        if (role == Qt::DisplayRole) {
            int result = value.toInt();
            if (result >= 1000000) {
                value = QString::number(result);
            }
        }
        return value
    }
    
    • mysql数据库有多种数据库引擎,其中MyIsam不支持数据库事务,默认一般是这个引擎,所以当你使用Qt中的transaction方法后commit提交时候,会发现不成功,其实事实上又是成功的,去数据库里面查看对应的结果又是正确的。有两个办法,第一就是将数据库引擎改成InnoDB,第二就是在提交后做个错误判断 if (database.commit() || !database.lastError().isValid()) ,错误不可用也说明是成功的。
    • 如果采用odbc数据源通信,则只需设置数据库名称setDatabaseName、设置用户名称setUserName、设置用户密码setPassword这三个参数即可,因为数据源配置的时候就已经设置好对应的主机地址和端口以及关联的数据库名称,所以在用odbc数据源通信的时候只需要再次验证用户信息即可。这里特别要注意的是setDatabaseName设置数据库名称要填写数据源配置的名称。
    • 经过大量的对比测试,包括插入、删除、批量、查询、分页等操作,千万量级数据,在Qt数据库部分响应速度这块,友好度排名依次是 sqlite > postgresql > oracle > mysql > odbc 。千万量级以上是 postgresql > oracle > mysql > sqlite > odbc 。亿级别以上是 oracle > postgresql > 其他。以上测试均建立在初学者水平基础上,至于分库分表、联合查询、缓存、内存数据库等各种高级知识点没用上。

    二、相关地址

    1. 体验地址:https://pan.baidu.com/s/1ZxG-oyUKe286LPMPxOrO2A 提取码:o05q 文件名:bin_dbtool.zip
    2. 国内站点:https://gitee.com/feiyangqingyun
    3. 国际站点:https://github.com/feiyangqingyun
    4. 个人主页:https://blog.csdn.net/feiyangqingyun
    5. 知乎主页:https://www.zhihu.com/people/feiyangqingyun/
    6. 文章导航:https://qtchina.blog.csdn.net/article/details/122839962

  • 相关阅读:
    「NOIP2011」聪明的质监员
    「CF5E」Bindian Signalizing
    「NOIP2017」列队
    「NOIP2016」愤怒的小鸟
    「牛客CSP-S2019赛前集训营2」服务器需求
    「牛客CSP-S2019赛前集训营1」仓鼠的石子游戏
    「SCOI2010」幸运数字
    函数求值一<找规律>
    梯形
    F(k)<(维护+枚举)(找规律+递推+枚举)>
  • 原文地址:https://www.cnblogs.com/feiyangqingyun/p/16413912.html
Copyright © 2020-2023  润新知