• 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.命令行操作

    1. //查看数据库
    2. .databases
    1. // 查看数据
    2. select * from tb_user;
    3. 1|yang|10
    1. //查看表
    2. .tables

    3.导入csv文件到sqlite

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

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

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

    qt操作sqlite封装

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

    QT += sql

    1. #ifndef SQLITEDB_H
    2. #define SQLITEDB_H
    3. #include
    4. #include
    5. #include
    6. #include
    7. #include
    8. #include
    9. #include
    10. #include
    11. #include
    12. #include
    13. class sqliteDb
    14. {
    15. public:
    16. sqliteDb();
    17. ~sqliteDb();
    18. public:
    19. bool setDbDir(QString dirPath);//设置数据库存放路径
    20. bool creatDbFile(QString dbName);//生成一个db文件
    21. bool reOpenSql(QString dbName);//打开连接
    22. bool closeSql();//关闭连接
    23. bool queryExec(QString dbName,QString sqlStr);//执行sql语句,不获取结果
    24. bool queryExec(QString dbName,QString sqlStr,QList> &data);//执行sql语句,并获取结果
    25. bool getData(QString dbName,QString tableName,QHash &data,QString sqlWhere=""); //获取数据
    26. bool getData(QString dbName,QString table,QList> &data,QString sqlWhere=""); //获取数据
    27. bool getData(QString dbName,QString tableName,QHash columndata,QList> &data,QString sqlWhere=""); //获取数据
    28. bool addData(QString dbName,QString tableName,QHash data);//增加
    29. bool delData(QString dbName,QString tableName,QString sqlWhere);//删除
    30. bool updateData(QString dbName,QString tableName,QHash data,QString sqlWhere="");//修改
    31. bool queryExec(QString sqlStr);//执行sql语句,不获取结果
    32. bool queryExec(QString sqlStr,QList> &data);//执行sql语句,并获取结果
    33. bool getData(QString tableName,QHash &data,QString sqlWhere=""); //获取数据
    34. bool getData(QString table,QList> &data,QString sqlWhere=""); //获取数据
    35. bool getData(QString tableName,QHash columndata,QList> &data,QString sqlWhere=""); //获取数据
    36. bool addData(QString tableName,QHash data);//增加
    37. bool delData(QString tableName,QString sqlWhere);//删除
    38. bool updateData(QString tableName,QHash data,QString sqlWhere="");//修改
    39. bool transaction();
    40. bool commit();
    41. QString getErrorSql();//获取错误的数据库语句
    42. private:
    43. QSqlDatabase db;
    44. QString dbFilePath;//数据库路径
    45. QString dbDir; //数据库文件夹
    46. QString databaseName;//数据库名字
    47. QString errorSqlText;//错误语句
    48. private:
    49. void errorSql(QString sql);//错误打印
    50. };
    51. #endif // SQLITEDB_H
    1. #include "sqlitedb.h"
    2. sqliteDb::sqliteDb()
    3. {
    4. dbDir = QDir::currentPath() ;
    5. }
    6. sqliteDb::~sqliteDb()
    7. {
    8. }
    9. //设置数据库存放路径
    10. bool sqliteDb::setDbDir(QString dirPath)
    11. {
    12. QDir dir(dirPath);
    13. if(dir.exists())
    14. {
    15. dbDir = dirPath;
    16. return true;
    17. }
    18. else
    19. {
    20. return false;
    21. }
    22. }
    23. //打开连接
    24. bool sqliteDb::reOpenSql(QString dbName)
    25. {
    26. QString fileName = (dbDir + "/"+dbName + ".db");
    27. if(!QFile::exists(fileName))
    28. {
    29. qWarning("error,db not exist");
    30. return false;//数据库不存在
    31. }
    32. QFileInfo file(fileName);
    33. if(file.suffix() != "db")
    34. return false;
    35. db = QSqlDatabase::database(dbName);
    36. if(!db.isValid())
    37. {
    38. db = QSqlDatabase::addDatabase("QSQLITE",dbName);
    39. db.setDatabaseName(fileName);
    40. if (!db.open())
    41. {
    42. return false;//打开失败
    43. }
    44. }
    45. dbFilePath = fileName;
    46. databaseName = dbName;//数据库名字
    47. return true;
    48. }
    49. //关闭连接
    50. bool sqliteDb::closeSql()
    51. {
    52. if(databaseName.isEmpty())
    53. return true;
    54. if(!QFile::exists(dbFilePath))
    55. {
    56. return false;//数据库不存在
    57. }
    58. db = QSqlDatabase::database(databaseName);
    59. if(!db.isValid())
    60. {
    61. return true;
    62. }
    63. db.close();
    64. db = QSqlDatabase::database();
    65. QSqlDatabase::removeDatabase(databaseName);
    66. databaseName = "";
    67. dbFilePath = "";
    68. return true;
    69. }
    70. //生成一个db文件
    71. bool sqliteDb::creatDbFile(QString dbName)
    72. {
    73. QString fileName = (dbDir + "/"+dbName + ".db");
    74. QFileInfo fileInfo(fileName);
    75. if(fileInfo.isFile()){
    76. qWarning("db已存在,创建失败");
    77. return false;
    78. }
    79. QFile file(fileName);
    80. if(file.open(QIODevice::WriteOnly))
    81. {
    82. file.close();
    83. }
    84. else
    85. {
    86. return false;
    87. }
    88. return true;
    89. }
    90. //错误打印
    91. void sqliteDb::errorSql(QString sql)
    92. {
    93. errorSqlText = sql;
    94. qCritical("%s",qPrintable(errorSqlText));
    95. //QString("数据库执行错误:%1 ")+sql.toUtf8().constData();
    96. }
    97. //获取错误的数据库语句
    98. QString sqliteDb::getErrorSql()
    99. {
    100. if(databaseName.isEmpty())
    101. {
    102. return "db not setting";//数据库未设置
    103. }
    104. return errorSqlText;
    105. }
    106. //执行sql语句,不获取结果
    107. bool sqliteDb::queryExec(QString dbName,QString queryStr)
    108. {
    109. if(databaseName.isEmpty())
    110. {
    111. if(!reOpenSql(dbName))
    112. {
    113. return false;
    114. }
    115. }
    116. QSqlQuery query(QSqlDatabase::database(dbName, true));
    117. if(!query.exec(queryStr))
    118. {
    119. errorSql(queryStr);
    120. return false;
    121. }
    122. return true;
    123. }
    124. //执行sql语句,并获取结果
    125. bool sqliteDb::queryExec(QString dbName,QString queryStr,QList> &data)
    126. {
    127. data.clear();
    128. if(databaseName.isEmpty())
    129. {
    130. if(!reOpenSql(dbName))
    131. {
    132. return false;
    133. }
    134. }
    135. QSqlQuery query(QSqlDatabase::database(dbName, true));
    136. if(!query.exec(queryStr))
    137. {
    138. errorSql(queryStr);
    139. return false;
    140. }
    141. QSqlRecord rec = query.record();
    142. while(query.next())
    143. {
    144. QHash rowData;
    145. for(int i =0;icount();i++)
    146. {
    147. QVariant::Type ty = query.value(i).type();
    148. if( QVariant::Type::Date == ty)
    149. {
    150. QDate temp = query.value(i).toDate();
    151. rowData[rec.fieldName(i)]=temp.toString("yyyy-MM-dd");
    152. }
    153. else if( QVariant::Type::Time == ty)
    154. {
    155. QTime temp = query.value(i).toTime();
    156. rowData[rec.fieldName(i)]=temp.toString("hh:mm:ss");
    157. }
    158. else if( QVariant::Type::DateTime == ty)
    159. {
    160. QDateTime temp = query.value(i).toDateTime();
    161. rowData[rec.fieldName(i)]=temp.toString("yyyy-MM-dd hh:mm:ss");
    162. }
    163. else
    164. rowData[rec.fieldName(i)]=query.value(i).toString();
    165. }
    166. data.append(rowData);
    167. }
    168. return true;
    169. }
    170. //获取数据
    171. bool sqliteDb::getData(QString dbName,QString tableName,QHash &data,QString sqlWhere)
    172. {
    173. data.clear();
    174. QList> dataList;
    175. if(!getData(dbName,tableName,dataList,sqlWhere))
    176. {
    177. return false;
    178. }
    179. if(dataList.count() > 0)
    180. {
    181. data = dataList[0];
    182. }
    183. return true;
    184. }
    185. //获取数据
    186. bool sqliteDb::getData(QString dbName,QString tableName,QList> &data,QString sqlWhere)
    187. {
    188. QString queryStr="select * from "+tableName;
    189. if(!sqlWhere.isEmpty())
    190. queryStr+=" "+sqlWhere;
    191. if(!queryExec(dbName,queryStr,data))
    192. {
    193. return false;
    194. }
    195. return true;
    196. }
    197. //获取数据
    198. bool sqliteDb::getData(QString dbName,QString tableName,QHash columndata,QList> &data,QString sqlWhere)
    199. {
    200. QString colunmStr;
    201. if(columndata.count() == 0)
    202. colunmStr = "*";
    203. else
    204. {
    205. QStringList keys = columndata.keys();
    206. for(auto key : keys)
    207. {
    208. QString column = QString("%1 AS `%2`").arg(key).arg(columndata[key]);
    209. if(!colunmStr.isEmpty())
    210. colunmStr += ",";
    211. colunmStr += column;
    212. }
    213. }
    214. QString queryStr = QString("SELECT %1 FROM %2 %3").arg(colunmStr).arg(tableName).arg( sqlWhere);
    215. if(!queryExec(dbName,queryStr,data))
    216. {
    217. return false;
    218. }
    219. return true;
    220. }
    221. //增加
    222. bool sqliteDb::addData(QString dbName,QString tableName,QHash data)
    223. {
    224. if(data.isEmpty())
    225. return false;
    226. QString queryStr="insert into "+tableName+" ";
    227. QString fieldStr="(",valueStr="values(";
    228. QHash::iterator it;
    229. for ( it = data.begin(); it != data.end(); ++it )
    230. {
    231. fieldStr+=it.key()+",";
    232. valueStr+="'"+it.value()+"',";
    233. }
    234. fieldStr=fieldStr.left(fieldStr.length()-1);
    235. valueStr=valueStr.left(valueStr.length()-1);
    236. fieldStr+=")";
    237. valueStr+=")";
    238. queryStr+=fieldStr+" "+valueStr;
    239. if(!queryExec(dbName,queryStr))
    240. {
    241. return false;
    242. }
    243. return true;
    244. }
    245. //删除
    246. bool sqliteDb::delData(QString dbName, QString tableName, QString sqlWhere)
    247. {
    248. QString queryStr="delete from "+tableName;
    249. if(!sqlWhere.isEmpty())
    250. queryStr+=" "+sqlWhere;
    251. if(!queryExec(dbName,queryStr))
    252. {
    253. return false;
    254. }
    255. return true;
    256. }
    257. //修改
    258. bool sqliteDb::updateData(QString dbName,QString tableName,QHash data,QString sqlWhere)
    259. {
    260. QString queryStr="update "+tableName+" ";
    261. QHash::iterator it;
    262. QString setStr="set ";
    263. for ( it = data.begin(); it != data.end(); ++it )
    264. {
    265. setStr+=it.key()+"='"+it.value()+"'";
    266. setStr+=",";
    267. }
    268. setStr=setStr.left(setStr.length()-1);
    269. queryStr+=setStr;
    270. if(!sqlWhere.isEmpty())
    271. queryStr+=" "+sqlWhere;
    272. if(!queryExec(dbName,queryStr))
    273. {
    274. return false;
    275. }
    276. return true;
    277. }
    278. bool sqliteDb::transaction()
    279. {
    280. if(databaseName.isEmpty())
    281. return false;
    282. return db.transaction();
    283. }
    284. bool sqliteDb::commit()
    285. {
    286. if(databaseName.isEmpty())
    287. return false;
    288. return db.commit();
    289. }
    290. //执行sql语句,不获取结果
    291. bool sqliteDb::queryExec(QString sqlStr)
    292. {
    293. if(databaseName.isEmpty())
    294. return false;
    295. return queryExec(databaseName,sqlStr);
    296. }
    297. //执行sql语句,并获取结果
    298. bool sqliteDb::queryExec(QString sqlStr,QList> &data)
    299. {
    300. if(databaseName.isEmpty())
    301. return false;
    302. return queryExec(databaseName,sqlStr,data);
    303. }
    304. //获取数据
    305. bool sqliteDb::getData(QString tableName,QHash &data,QString sqlWhere)
    306. {
    307. if(databaseName.isEmpty())
    308. return false;
    309. return getData(databaseName,tableName,data,sqlWhere);
    310. }
    311. //获取数据
    312. bool sqliteDb::getData(QString table,QList> &data,QString sqlWhere)
    313. {
    314. if(databaseName.isEmpty())
    315. return false;
    316. return getData(databaseName,table,data,sqlWhere);
    317. }
    318. //获取数据
    319. bool sqliteDb::getData(QString tableName,QHash columndata,QList> &data,QString sqlWhere)
    320. {
    321. if(databaseName.isEmpty())
    322. return false;
    323. return getData(databaseName,tableName,columndata,data,sqlWhere);
    324. }
    325. //增加
    326. bool sqliteDb::addData(QString tableName,QHash data)
    327. {
    328. if(databaseName.isEmpty())
    329. return false;
    330. return addData(databaseName,tableName,data);
    331. }
    332. //删除
    333. bool sqliteDb::delData(QString tableName,QString sqlWhere)
    334. {
    335. if(databaseName.isEmpty())
    336. return false;
    337. return delData(databaseName,tableName,sqlWhere);
    338. }
    339. //修改
    340. bool sqliteDb::updateData(QString tableName,QHash data,QString sqlWhere)
    341. {
    342. if(databaseName.isEmpty())
    343. return false;
    344. return updateData(databaseName,tableName,data,sqlWhere);
    345. }
    346. //

     使用举例

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

    1. #include "dbhelper.h"
    2. #include "cglobal.h"
    3. Dbhelper::Dbhelper()
    4. {
    5. db = new sqliteDb();
    6. init_table_0 = R"(
    7. CREATE TABLE IF NOT EXISTS tb_user (
    8. id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
    9. name CHAR (50) NOT NULL,
    10. age INTEGER
    11. );)";
    12. }
    13. Dbhelper::~Dbhelper()
    14. {
    15. if(db!= nullptr){
    16. db->closeSql();
    17. delete db;
    18. }
    19. }
    20. int Dbhelper::createTable()
    21. {
    22. db->setDbDir(DATA_PATH);
    23. bool ret = db->creatDbFile(DB_NAME);
    24. if(!ret){
    25. return -1;
    26. }
    27. ret = db->reOpenSql(DB_NAME);
    28. if(ret){
    29. db->queryExec(QString::fromStdString(init_table_0));
    30. db->queryExec(QString::fromStdString(init_table_1));
    31. db->queryExec(QString::fromStdString(init_table_2));
    32. }
    33. return 0;
    34. }

    简单使用:

    1. Dbhelper mydb;
    2. //若库不存在则自动创建库和表
    3. mydb.createTable();
    4. //打开数据库
    5. auto ret = mydb.db->reOpenSql(DB_NAME);
    6. if(!ret){
    7. qCritical("打开数据库失败");
    8. }
    9. //插入一条测试数据
    10. QHash data;
    11. data["name"] = "yang";
    12. data["age"] = "10";
    13. mydb.db->addData("tb_user",data);
    14. //......

    注意事项

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

    1. //执行sql语句,并获取结果
    2. bool sqliteDb::queryExec(QString dbName,QString queryStr,QList> &data)
    3. {
    4. if(QSqlDatabase::contains("default")){
    5. qDebug() << "query error,now in use";
    6. return false;
    7. }
    8. data.clear();
    9. {
    10. QSqlDatabase mdb;
    11. {
    12. mdb= QSqlDatabase::addDatabase("QSQLITE","default");
    13. mdb.setDatabaseName("./liuliang.db");
    14. auto ret = mdb.open();
    15. if(!ret){
    16. qCritical("error,open",qPrintable(errorSqlText));
    17. }
    18. }
    19. QSqlQuery query(mdb);
    20. if(!query.exec(queryStr))
    21. {
    22. qDebug() << mdb.lastError();
    23. errorSql(queryStr);
    24. return false;
    25. }
    26. QSqlRecord rec = query.record();
    27. while(query.next())
    28. {
    29. QHash rowData;
    30. for(int i =0;icount();i++)
    31. {
    32. QVariant::Type ty = query.value(i).type();
    33. if( QVariant::Type::Date == ty)
    34. {
    35. QDate temp = query.value(i).toDate();
    36. rowData[rec.fieldName(i)]=temp.toString("yyyy-MM-dd");
    37. }
    38. else if( QVariant::Type::Time == ty)
    39. {
    40. QTime temp = query.value(i).toTime();
    41. rowData[rec.fieldName(i)]=temp.toString("hh:mm:ss");
    42. }
    43. else if( QVariant::Type::DateTime == ty)
    44. {
    45. QDateTime temp = query.value(i).toDateTime();
    46. rowData[rec.fieldName(i)]=temp.toString("yyyy-MM-dd hh:mm:ss");
    47. }
    48. else
    49. rowData[rec.fieldName(i)]=query.value(i).toString();
    50. }
    51. data.append(rowData);
    52. }
    53. }
    54. qDebug() << "query ok";
    55. QSqlDatabase::removeDatabase("default");
    56. return true;
    57. }

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

    Qt字节转换

    1. #include "stringutils.h"
    2. #include
    3. #include //解决QBytearray中文乱码问题
    4. #include
    5. //将1-9 a-f字符转化为对应的整数
    6. char ConvertHexChar(char ch)
    7. {
    8. if((ch >= '0') && (ch <= '9'))
    9. return ch-0x30;
    10. else if((ch >= 'A') && (ch <= 'F'))
    11. return ch-'A'+10;
    12. else if((ch >= 'a') && (ch <= 'f'))
    13. return ch-'a'+10;
    14. else return (-1);
    15. }
    16. //将字符型进制转化为16进制
    17. QByteArray QString2Hex(QString str)
    18. {
    19. QByteArray senddata;
    20. int hexdata,lowhexdata;
    21. int hexdatalen = 0;
    22. int len = str.length();
    23. senddata.resize(len/2);
    24. char lstr,hstr;
    25. for(int i=0; i
    26. {
    27. hstr=str[i].toLatin1(); //字符型
    28. if(hstr == ' ')
    29. {
    30. i++;
    31. continue;
    32. }
    33. i++;
    34. if(i >= len)
    35. break;
    36. lstr = str[i].toLatin1();
    37. hexdata = ConvertHexChar(hstr);
    38. lowhexdata = ConvertHexChar(lstr);
    39. if((hexdata == 16) || (lowhexdata == 16))
    40. break;
    41. else
    42. hexdata = hexdata*16+lowhexdata;
    43. i++;
    44. senddata[hexdatalen] = (char)hexdata;
    45. hexdatalen++;
    46. }
    47. senddata.resize(hexdatalen);
    48. return senddata;
    49. }
    50. //将接收的一串QByteArray类型的16进制,转化为对应的字符串16进制
    51. QString Hex2QString(QByteArray str)
    52. {
    53. QDataStream out(&str,QIODevice::ReadWrite); //将str的数据 读到out里面去
    54. QString buf;
    55. while(!out.atEnd())
    56. {
    57. qint8 outChar = 0;
    58. out >> outChar; //每次一个字节的填充到 outchar
    59. QString str = QString("%1").arg(outChar&0xFF,2,16,QLatin1Char('0')).toUpper() + QString(""); //2 字符宽度
    60. buf += str;
    61. }
    62. return buf;
    63. }
    64. QString ShowStr(QByteArray arr)
    65. {
    66. //QDataStream out(&str,QIODevice::ReadWrite); //将str的数据 读到out里面去
    67. //QString buf;
    68. //buf.prepend(str);
    69. // while(!out.atEnd())
    70. // {
    71. // qint8 outChar = 0;
    72. // out >> outChar; //每次一个字节的填充到 outchar
    73. // QString str = QString("%1").arg(outChar&0xFF,2,16,QLatin1Char('0')).toUpper() + QString(" "); //2 字符宽度
    74. // buf += str;
    75. // }
    76. QTextCodec *tc = QTextCodec::codecForName("GBK");
    77. QString tmpQStr = tc->toUnicode(arr);
    78. return tmpQStr;
    79. }
    80. //将接收的一串QByteArray类型的16进制,每2个16进制转化为1个字的16进制的字符串
    81. QString Convert4Hex(QByteArray str)
    82. {
    83. QDataStream out(&str,QIODevice::ReadWrite); //将str的数据 读到out里面去
    84. QString buf;
    85. while(!out.atEnd())
    86. {
    87. qint16 outChar = 0;
    88. out>>outChar; //每次一个字节的填充到 outchar
    89. QString str = QString("%1").arg(outChar&0xFFFF,4,16,QLatin1Char('0')).toUpper() + QString(" "); //2 字符宽度
    90. buf += str;
    91. }
    92. return buf;
    93. }

    引用

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

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

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

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

  • 相关阅读:
    基于C++的人脸过渡项目
    【TypeScript】中接口的详细介绍
    第 45 届国际大学生程序设计竞赛(ICPC)亚洲区域赛(沈阳),签到题4题
    springboot thymeleaf使用
    self-attention、transformer、bert理解
    【C++】list常用接口
    面试必备杀技:SQL查询专项训练!
    22.07.03.05(Wireshark 抓包并分析)
    SpringBoot学习笔记-配置MySQL与实现注册登录模块(中)
    专利申请需要多少钱
  • 原文地址:https://blog.csdn.net/qq8864/article/details/126215755