Qt操作Sqlite类封装,及命令行导入csv文件到Sqlite数据库

简介: Qt操作Sqlite类封装,及命令行导入csv文件到Sqlite数据库

日常工作中,有时候需要对数据进行分析。如果能把待分析的数据导入sqllite数据库,是种不错的分析手段。或者需要导入其他数据库中的数据,做数据迁移用,比如可以把其他数据库中的表数据导出为csv文件,再把csv文件导入到sqllite。


用Qt来操作sqlite,可以做些带界面和图表的分析,使用很方便。


这里记录下导入csv文件到sqlite数据库的操作方法及sqlite的封装,留作备忘。


浏览sqllite数据库的客户端工具,我常用的是SQLiteSpy,仅4M大小,小巧简单。



导入csv到sqlite


使用sqlite3.exe命令行工具。这个sqllite数据库带的有这个工具,可以直接下载使用。

操作的步骤:


1.打开数据库文件(前提存在db文件,且里面有相应的表结构)


.\sqlite3.exe .\test.db


2.命令行操作


 //查看数据库
 .databases


// 查看数据
select * from tb_user;
1|yang|10


//查看表
.tables


3.导入csv文件到sqlite


这其中有个特别需要注意的问题是:csv文件的编码问题,必须为utf-8格式,utf-8-bom不行。


// 必须修改为,分隔符 
.separator ","
// 查看表结构
.schema tb_data
// 导入csv数据到表中 (前提 结构必须一致)                                                           
.import dbo_data.csv tb_data


以上操作即完成了csv文件数据入库的操作。


qt操作sqlite封装


Qt中操作数据库,.pro文件中,需要添加上:


QT += sql


#ifndef SQLITEDB_H
#define SQLITEDB_H
#include <QDir>
#include <QDate>
#include <QDateTime>
#include <QFileInfo>
#include <QString>
#include <QTime>
#include <QSqlDatabase>
#include <QSqlRecord>
#include <QSqlQuery>
#include <QVariant>
class sqliteDb
{
public:
    sqliteDb();
    ~sqliteDb();
public:
    bool setDbDir(QString dirPath);//设置数据库存放路径
    bool creatDbFile(QString dbName);//生成一个db文件
    bool reOpenSql(QString dbName);//打开连接
    bool closeSql();//关闭连接
    bool queryExec(QString dbName,QString sqlStr);//执行sql语句,不获取结果
    bool queryExec(QString dbName,QString sqlStr,QList<QHash<QString,QString>> &data);//执行sql语句,并获取结果
    bool getData(QString dbName,QString tableName,QHash<QString,QString> &data,QString sqlWhere=""); //获取数据
    bool getData(QString dbName,QString table,QList<QHash<QString,QString>> &data,QString sqlWhere=""); //获取数据
    bool getData(QString dbName,QString tableName,QHash<QString,QString> columndata,QList<QHash<QString,QString>> &data,QString sqlWhere=""); //获取数据
    bool addData(QString dbName,QString tableName,QHash<QString,QString> data);//增加
    bool delData(QString dbName,QString tableName,QString sqlWhere);//删除
    bool updateData(QString dbName,QString tableName,QHash<QString,QString> data,QString sqlWhere="");//修改
    bool queryExec(QString sqlStr);//执行sql语句,不获取结果
    bool queryExec(QString sqlStr,QList<QHash<QString,QString>> &data);//执行sql语句,并获取结果
    bool getData(QString tableName,QHash<QString,QString> &data,QString sqlWhere=""); //获取数据
    bool getData(QString table,QList<QHash<QString,QString>> &data,QString sqlWhere=""); //获取数据
    bool getData(QString tableName,QHash<QString,QString> columndata,QList<QHash<QString,QString>> &data,QString sqlWhere=""); //获取数据
    bool addData(QString tableName,QHash<QString,QString> data);//增加
    bool delData(QString tableName,QString sqlWhere);//删除
    bool updateData(QString tableName,QHash<QString,QString> data,QString sqlWhere="");//修改
    bool transaction();
    bool commit();
    QString getErrorSql();//获取错误的数据库语句
private:
    QSqlDatabase db;
    QString dbFilePath;//数据库路径
    QString dbDir; //数据库文件夹
    QString databaseName;//数据库名字
    QString errorSqlText;//错误语句
private:
    void errorSql(QString sql);//错误打印
};
#endif // SQLITEDB_H


#include "sqlitedb.h"
sqliteDb::sqliteDb()
{
    dbDir = QDir::currentPath() ;
}
sqliteDb::~sqliteDb()
{
}
//设置数据库存放路径
bool sqliteDb::setDbDir(QString dirPath)
{
    QDir dir(dirPath);
    if(dir.exists())
    {
        dbDir = dirPath;
        return true;
    }
    else
    {
        return false;
    }
}
//打开连接
bool sqliteDb::reOpenSql(QString dbName)
{
    QString fileName = (dbDir + "/"+dbName + ".db");
    if(!QFile::exists(fileName))
    {
        qWarning("error,db not exist");
        return false;//数据库不存在
    }
    QFileInfo file(fileName);
    if(file.suffix() != "db")
        return false;
    db = QSqlDatabase::database(dbName);
    if(!db.isValid())
    {
        db = QSqlDatabase::addDatabase("QSQLITE",dbName);
        db.setDatabaseName(fileName);
        if (!db.open())
        {
            return false;//打开失败
        }
    }
    dbFilePath = fileName;
    databaseName = dbName;//数据库名字
    return true;
}
//关闭连接
bool sqliteDb::closeSql()
{
    if(databaseName.isEmpty())
        return true;
    if(!QFile::exists(dbFilePath))
    {
        return false;//数据库不存在
    }
    db = QSqlDatabase::database(databaseName);
    if(!db.isValid())
    {
        return true;
    }
    db.close();
    db = QSqlDatabase::database();
    QSqlDatabase::removeDatabase(databaseName);
    databaseName = "";
    dbFilePath = "";
    return true;
}
//生成一个db文件
bool sqliteDb::creatDbFile(QString dbName)
{
    QString fileName = (dbDir + "/"+dbName + ".db");
    QFileInfo fileInfo(fileName);
    if(fileInfo.isFile()){
        qWarning("db已存在,创建失败");
        return false;
    }
    QFile file(fileName);
    if(file.open(QIODevice::WriteOnly))
    {
        file.close();
    }
    else
    {
        return false;
    }
    return true;
}
//错误打印
void sqliteDb::errorSql(QString sql)
{
    errorSqlText = sql;
    qCritical("%s",qPrintable(errorSqlText));
    //QString("数据库执行错误:%1 ")+sql.toUtf8().constData();
}
//获取错误的数据库语句
QString sqliteDb::getErrorSql()
{
    if(databaseName.isEmpty())
    {
        return "db  not setting";//数据库未设置
    }
    return errorSqlText;
}
//执行sql语句,不获取结果
bool sqliteDb::queryExec(QString dbName,QString queryStr)
{
    if(databaseName.isEmpty())
    {
        if(!reOpenSql(dbName))
        {
            return false;
        }
    }
    QSqlQuery query(QSqlDatabase::database(dbName, true));
    if(!query.exec(queryStr))
    {
        errorSql(queryStr);
        return false;
    }
    return  true;
}
//执行sql语句,并获取结果
bool sqliteDb::queryExec(QString dbName,QString queryStr,QList<QHash<QString,QString>> &data)
{
    data.clear();
    if(databaseName.isEmpty())
    {
        if(!reOpenSql(dbName))
        {
            return false;
        }
    }
    QSqlQuery query(QSqlDatabase::database(dbName, true));
    if(!query.exec(queryStr))
    {
        errorSql(queryStr);
        return false;
    }
    QSqlRecord rec = query.record();
    while(query.next())
    {
        QHash<QString,QString> rowData;
        for(int i =0;i<rec.count();i++)
        {
            QVariant::Type ty =  query.value(i).type();
            if( QVariant::Type::Date == ty)
            {
                QDate temp = query.value(i).toDate();
                rowData[rec.fieldName(i)]=temp.toString("yyyy-MM-dd");
            }
            else if( QVariant::Type::Time == ty)
            {
                QTime temp = query.value(i).toTime();
                rowData[rec.fieldName(i)]=temp.toString("hh:mm:ss");
            }
            else if( QVariant::Type::DateTime == ty)
            {
                QDateTime temp = query.value(i).toDateTime();
                rowData[rec.fieldName(i)]=temp.toString("yyyy-MM-dd hh:mm:ss");
            }
            else
                rowData[rec.fieldName(i)]=query.value(i).toString();
        }
        data.append(rowData);
    }
    return  true;
}
//获取数据
bool sqliteDb::getData(QString dbName,QString tableName,QHash<QString,QString> &data,QString sqlWhere)
{
    data.clear();
    QList<QHash<QString,QString>> dataList;
    if(!getData(dbName,tableName,dataList,sqlWhere))
    {
        return false;
    }
    if(dataList.count() > 0)
    {
        data = dataList[0];
    }
    return true;
}
//获取数据
bool sqliteDb::getData(QString dbName,QString tableName,QList<QHash<QString,QString>> &data,QString sqlWhere)
{
    QString queryStr="select * from "+tableName;
    if(!sqlWhere.isEmpty())
        queryStr+=" "+sqlWhere;
    if(!queryExec(dbName,queryStr,data))
    {
        return  false;
    }
    return  true;
}
//获取数据
bool sqliteDb::getData(QString dbName,QString tableName,QHash<QString,QString> columndata,QList<QHash<QString,QString>> &data,QString sqlWhere)
{
    QString colunmStr;
    if(columndata.count() == 0)
        colunmStr = "*";
    else
    {
        QStringList keys = columndata.keys();
        for(auto key : keys)
        {
            QString column = QString("%1 AS `%2`").arg(key).arg(columndata[key]);
            if(!colunmStr.isEmpty())
                colunmStr += ",";
            colunmStr += column;
        }
    }
    QString queryStr = QString("SELECT %1 FROM %2 %3").arg(colunmStr).arg(tableName).arg( sqlWhere);
    if(!queryExec(dbName,queryStr,data))
    {
        return  false;
    }
    return  true;
}
//增加
bool sqliteDb::addData(QString dbName,QString tableName,QHash<QString,QString> data)
{
    if(data.isEmpty())
        return false;
    QString queryStr="insert into "+tableName+" ";
    QString fieldStr="(",valueStr="values(";
    QHash<QString,QString>::iterator it;
    for ( it = data.begin(); it != data.end(); ++it )
    {
        fieldStr+=it.key()+",";
        valueStr+="'"+it.value()+"',";
    }
    fieldStr=fieldStr.left(fieldStr.length()-1);
    valueStr=valueStr.left(valueStr.length()-1);
    fieldStr+=")";
    valueStr+=")";
    queryStr+=fieldStr+" "+valueStr;
    if(!queryExec(dbName,queryStr))
    {
        return false;
    }
    return true;
}
//删除
bool sqliteDb::delData(QString dbName, QString tableName, QString sqlWhere)
{
    QString queryStr="delete from "+tableName;
    if(!sqlWhere.isEmpty())
        queryStr+=" "+sqlWhere;
    if(!queryExec(dbName,queryStr))
    {
        return false;
    }
    return true;
}
//修改
bool sqliteDb::updateData(QString dbName,QString tableName,QHash<QString,QString> data,QString sqlWhere)
{
    QString queryStr="update "+tableName+" ";
    QHash<QString,QString>::iterator it;
    QString setStr="set ";
    for ( it = data.begin(); it != data.end(); ++it )
    {
        setStr+=it.key()+"='"+it.value()+"'";
        setStr+=",";
    }
    setStr=setStr.left(setStr.length()-1);
    queryStr+=setStr;
    if(!sqlWhere.isEmpty())
        queryStr+=" "+sqlWhere;
    if(!queryExec(dbName,queryStr))
    {
        return false;
    }
    return true;
}
bool sqliteDb::transaction()
{
    if(databaseName.isEmpty())
        return false;
    return  db.transaction();
}
bool sqliteDb::commit()
{
    if(databaseName.isEmpty())
        return false;
    return  db.commit();
}
//执行sql语句,不获取结果
bool sqliteDb::queryExec(QString sqlStr)
{
    if(databaseName.isEmpty())
        return false;
    return  queryExec(databaseName,sqlStr);
}
//执行sql语句,并获取结果
bool sqliteDb::queryExec(QString sqlStr,QList<QHash<QString,QString>> &data)
{
    if(databaseName.isEmpty())
        return false;
    return  queryExec(databaseName,sqlStr,data);
}
//获取数据
bool sqliteDb::getData(QString tableName,QHash<QString,QString> &data,QString sqlWhere)
{
    if(databaseName.isEmpty())
        return false;
    return  getData(databaseName,tableName,data,sqlWhere);
}
//获取数据
bool sqliteDb::getData(QString table,QList<QHash<QString,QString>> &data,QString sqlWhere)
{
    if(databaseName.isEmpty())
        return false;
    return  getData(databaseName,table,data,sqlWhere);
}
//获取数据
bool sqliteDb::getData(QString tableName,QHash<QString,QString> columndata,QList<QHash<QString,QString>> &data,QString sqlWhere)
{
    if(databaseName.isEmpty())
        return false;
    return  getData(databaseName,tableName,columndata,data,sqlWhere);
}
//增加
bool sqliteDb::addData(QString tableName,QHash<QString,QString> data)
{
    if(databaseName.isEmpty())
        return false;
    return  addData(databaseName,tableName,data);
}
//删除
bool sqliteDb::delData(QString tableName,QString sqlWhere)
{
    if(databaseName.isEmpty())
        return false;
    return  delData(databaseName,tableName,sqlWhere);
}
//修改
bool sqliteDb::updateData(QString tableName,QHash<QString,QString> data,QString sqlWhere)
{
    if(databaseName.isEmpty())
        return false;
    return  updateData(databaseName,tableName,data,sqlWhere);
}
//


使用举例


新建一个dbhelper类,作为具体的操作使用。


#include "dbhelper.h"
#include "cglobal.h"
Dbhelper::Dbhelper()
{
    db = new sqliteDb();
    init_table_0 = R"(
                 CREATE TABLE IF NOT EXISTS  tb_user (
                 id   INTEGER   PRIMARY KEY AUTOINCREMENT NOT NULL,
                 name CHAR (50) NOT NULL,
                 age  INTEGER
                 );)";
}
Dbhelper::~Dbhelper()
{
    if(db!= nullptr){
        db->closeSql();
        delete db;
    }
}
int Dbhelper::createTable()
{
    db->setDbDir(DATA_PATH);
    bool ret = db->creatDbFile(DB_NAME);
    if(!ret){
        return -1;
    }
    ret = db->reOpenSql(DB_NAME);
    if(ret){
        db->queryExec(QString::fromStdString(init_table_0));
        db->queryExec(QString::fromStdString(init_table_1));
        db->queryExec(QString::fromStdString(init_table_2));
    }
    return 0;
}


简单使用:


    Dbhelper mydb;
    //若库不存在则自动创建库和表
    mydb.createTable();
    //打开数据库
    auto ret = mydb.db->reOpenSql(DB_NAME);
    if(!ret){
       qCritical("打开数据库失败");
    }
    //插入一条测试数据
    QHash<QString,QString> data;
    data["name"] = "yang";
    data["age"] = "10";
    mydb.db->addData("tb_user",data);
    //......


注意事项


由于QSqlDatabase机制问题,不能跨线程访问,上述封装的连接和使用只能在同一个线程中使用。若需要放在多线程中使用,则需要改下query的实现方法,如:


//执行sql语句,并获取结果
bool sqliteDb::queryExec(QString dbName,QString queryStr,QList<QHash<QString,QString>> &data)
{
    if(QSqlDatabase::contains("default")){
         qDebug() << "query error,now in use";
         return false;
    }
    data.clear();
    {
        QSqlDatabase mdb;
        {
            mdb= QSqlDatabase::addDatabase("QSQLITE","default");
            mdb.setDatabaseName("./liuliang.db");
            auto ret =  mdb.open();
            if(!ret){
                 qCritical("error,open",qPrintable(errorSqlText));
            }
        }
        QSqlQuery query(mdb);
        if(!query.exec(queryStr))
        {
            qDebug() << mdb.lastError();
            errorSql(queryStr);
            return false;
        }
        QSqlRecord rec = query.record();
        while(query.next())
        {
            QHash<QString,QString> rowData;
            for(int i =0;i<rec.count();i++)
            {
                QVariant::Type ty =  query.value(i).type();
                if( QVariant::Type::Date == ty)
                {
                    QDate temp = query.value(i).toDate();
                    rowData[rec.fieldName(i)]=temp.toString("yyyy-MM-dd");
                }
                else if( QVariant::Type::Time == ty)
                {
                    QTime temp = query.value(i).toTime();
                    rowData[rec.fieldName(i)]=temp.toString("hh:mm:ss");
                }
                else if( QVariant::Type::DateTime == ty)
                {
                    QDateTime temp = query.value(i).toDateTime();
                    rowData[rec.fieldName(i)]=temp.toString("yyyy-MM-dd hh:mm:ss");
                }
                else
                    rowData[rec.fieldName(i)]=query.value(i).toString();
            }
            data.append(rowData);
        }
    }
    qDebug() << "query ok";
    QSqlDatabase::removeDatabase("default");
    return  true;
}



SQLiteDatabse实质上是将数据写入一个文件,我们可以得知SQLiteDatabse是文件级别的锁。多个线程可以同时读;但是多个线程同时读/写时:如读先发生,写会被阻塞直至读完毕,写才会继续执行;如写先发生,读会被阻塞直至写完毕,读才会继续执行。


Qt字节转换


#include "stringutils.h"
#include <QDebug>
#include <QTextCodec> //解决QBytearray中文乱码问题
#include <QDataStream>
//将1-9 a-f字符转化为对应的整数
 char ConvertHexChar(char ch)
    {
        if((ch >= '0') && (ch <= '9'))
            return ch-0x30;
        else if((ch >= 'A') && (ch <= 'F'))
            return ch-'A'+10;
        else if((ch >= 'a') && (ch <= 'f'))
            return ch-'a'+10;
        else return (-1);
    }
//将字符型进制转化为16进制
 QByteArray QString2Hex(QString str)
    {
        QByteArray senddata;
        int hexdata,lowhexdata;
        int hexdatalen = 0;
        int len = str.length();
        senddata.resize(len/2);
        char lstr,hstr;
        for(int i=0; i<len; )
        {
            hstr=str[i].toLatin1();   //字符型
            if(hstr == ' ')
            {
                i++;
                continue;
            }
            i++;
            if(i >= len)
                break;
            lstr = str[i].toLatin1();
            hexdata = ConvertHexChar(hstr);
            lowhexdata = ConvertHexChar(lstr);
            if((hexdata == 16) || (lowhexdata == 16))
                break;
            else
                hexdata = hexdata*16+lowhexdata;
            i++;
            senddata[hexdatalen] = (char)hexdata;
            hexdatalen++;
        }
        senddata.resize(hexdatalen);
        return senddata;
    }
//将接收的一串QByteArray类型的16进制,转化为对应的字符串16进制
 QString Hex2QString(QByteArray str)
 {
     QDataStream out(&str,QIODevice::ReadWrite);   //将str的数据 读到out里面去
     QString buf;
     while(!out.atEnd())
     {
           qint8 outChar = 0;
           out >> outChar;   //每次一个字节的填充到 outchar
           QString str = QString("%1").arg(outChar&0xFF,2,16,QLatin1Char('0')).toUpper() + QString("");   //2 字符宽度
           buf += str;
     }
     return buf;
 }
 QString ShowStr(QByteArray arr)
 {
     //QDataStream out(&str,QIODevice::ReadWrite);   //将str的数据 读到out里面去
     //QString buf;
     //buf.prepend(str);
//     while(!out.atEnd())
//     {
//           qint8 outChar = 0;
//           out >> outChar;   //每次一个字节的填充到 outchar
//           QString str = QString("%1").arg(outChar&0xFF,2,16,QLatin1Char('0')).toUpper() + QString(" ");   //2 字符宽度
//           buf += str;
//     }
     QTextCodec *tc = QTextCodec::codecForName("GBK");
     QString tmpQStr = tc->toUnicode(arr);
     return tmpQStr;
 }
//将接收的一串QByteArray类型的16进制,每2个16进制转化为1个字的16进制的字符串
 QString Convert4Hex(QByteArray str)
 {
     QDataStream out(&str,QIODevice::ReadWrite);   //将str的数据 读到out里面去
     QString buf;
     while(!out.atEnd())
     {
           qint16 outChar = 0;
           out>>outChar;   //每次一个字节的填充到 outchar
           QString str = QString("%1").arg(outChar&0xFFFF,4,16,QLatin1Char('0')).toUpper() + QString(" ");   //2 字符宽度
           buf += str;
     }
     return buf;
 }


引用


Qt中操作SQLite数据库_龚建波的博客-CSDN博客_qt sqlite


QSqlDatabase二三事_龚建波的博客-CSDN博客


Qt使用sqlite数据库,查询数据卡顿导致其他数据偶尔插入失败_ouyang1988503的博客-CSDN博客


SQLiteDatabase 多线程访问需要注意的问题_苍痕的博客-CSDN博客

相关文章
|
2月前
|
SQL 关系型数据库 MySQL
SQL命令行退出操作指南:轻松掌握不同数据库环境下的退出技巧
在数据库管理与开发过程中,经常需要通过SQL命令行工具(如MySQL的mysql客户端、PostgreSQL的psql、SQL Server的sqlcmd等)与数据库进行交互
341 59
|
2月前
|
存储 SQL 关系型数据库
Mysql学习笔记(二):数据库命令行代码总结
这篇文章是关于MySQL数据库命令行操作的总结,包括登录、退出、查看时间与版本、数据库和数据表的基本操作(如创建、删除、查看)、数据的增删改查等。它还涉及了如何通过SQL语句进行条件查询、模糊查询、范围查询和限制查询,以及如何进行表结构的修改。这些内容对于初学者来说非常实用,是学习MySQL数据库管理的基础。
138 6
|
2月前
|
SQL 关系型数据库 MySQL
数据库导入SQL文件:全面解析与操作指南
在数据库管理中,将SQL文件导入数据库是一个常见且重要的操作。无论是迁移数据、恢复备份,还是测试和开发环境搭建,掌握如何正确导入SQL文件都至关重要。本文将详细介绍数据库导入SQL文件的全过程,包括准备工作、操作步骤以及常见问题解决方案,旨在为数据库管理员和开发者提供全面的操作指南。一、准备工作在导
421 0
|
9天前
|
关系型数据库 MySQL 数据库
数据库数据恢复—MYSQL数据库文件损坏的数据恢复案例
mysql数据库文件ibdata1、MYI、MYD损坏。 故障表现:1、数据库无法进行查询等操作;2、使用mysqlcheck和myisamchk无法修复数据库。
|
13天前
|
SQL 关系型数据库 MySQL
MySQL导入.sql文件后数据库乱码问题
本文分析了导入.sql文件后数据库备注出现乱码的原因,包括字符集不匹配、备注内容编码问题及MySQL版本或配置问题,并提供了详细的解决步骤,如检查和统一字符集设置、修改客户端连接方式、检查MySQL配置等,确保导入过程顺利。
|
19天前
|
SQL 存储 BI
gbase 8a 数据库 SQL合并类优化——不同数据统计周期合并为一条SQL语句
gbase 8a 数据库 SQL合并类优化——不同数据统计周期合并为一条SQL语句
|
21天前
|
Oracle 关系型数据库 数据库
Oracle数据恢复—Oracle数据库文件有坏快损坏的数据恢复案例
一台Oracle数据库打开报错,报错信息: “system01.dbf需要更多的恢复来保持一致性,数据库无法打开”。管理员联系我们数据恢复中心寻求帮助,并提供了Oracle_Home目录的所有文件。用户方要求恢复zxfg用户下的数据。 由于数据库没有备份,无法通过备份去恢复数据库。
|
2月前
|
SQL 关系型数据库 MySQL
|
2月前
|
存储 关系型数据库 MySQL
PACS系统 中 dicom 文件在mysql 8.0 数据库中的 存储和读取(pydicom 库使用)
PACS系统 中 dicom 文件在mysql 8.0 数据库中的 存储和读取(pydicom 库使用)
41 2
|
2月前
|
SQL 存储 关系型数据库
SQL文件导入MySQL数据库的详细指南
数据库中的数据转移是一项常规任务,无论是在数据迁移过程中,还是在数据备份、还原场景中,导入导出SQL文件显得尤为重要。特别是在使用MySQL数据库时,如何将SQL文件导入数据库是一项基本技能。本文将详细介绍如何将SQL文件导入MySQL数据库,并提供一个清晰、完整的步骤指南。这篇文章的内容字数大约在
322 1