本文标题:Qt数据库操作 本文地址: http://techieliang.com/2017/11/335/
1. 基本操作
1.1. 连接
- if(!QSqlDatabase::contains()) {
- QSqlDatabase database = QSqlDatabase::addDatabase("QSQLITE");//第二参数不提供名字,使用默认名称,第一个参数为数据库类型名
- database.setDatabaseName(m_db_file_name);//数据库名--sqlite是文件名,sqlite不用写下面的配置
- database.setHostName("techieliang.com"); //数据库主机名
- database.setUserName("user"); //数据库用户名
- database.setPassword("******"); //数据库密码
- if(!database.open()) {
- qDebug()<<database.lastError();
- }
- }
注意addDatabase有两个参数,第二个参数是用于给此连接命名的,若不命名则为默认名称。
默认名称为:qt_sql_default_connection
- static QSqlDatabase addDatabase(QSqlDriver* driver,
- const QString& connectionName = QLatin1String(defaultConnection));
1.2. 断开连接
虽然关闭程序以后默认会断开,不会导致文件永久占用,但是建议数据库用完主动断开
- QSqlDatabase database = QSqlDatabase::database();//根据连接名称获取数据库,不填写则为默认连接名
- database.close();
1.3. sql指令操作
简单一次操作:
- const static QString mInsertCategorySql =
- "insert into category values (null,?)";//增,name名字
如果有自增量,或其他不需要输入的字段,只需要在对应位置输入null即可,注意不是字符串null
对于需要填充的地方可以用?代替,后续可直接用addBindValue或者bindValue指令替换,按照?出现顺序替换
- bool SqlManager::InsertCategorySql(QString name) {
- QSqlQuery sql_query;//默认构造使用默认数据库
- sql_query.prepare(mInsertCategorySql);
- sql_query.addBindValue(name);
- if(!sql_query.exec()) {
- qDebug() << sql_query.lastError();
- return false;
- }
- return true;
- }
多字段:
- const static QString mInsertJournalSql =
- "insert into journal values (null,:catagory,:date,:value,:remark,:auditing)";
使用”:XXXX”作为占位符,使用bindValue指令替换
注意,只需要给出对应类型即可,Qt会自动进行转换,包括日期、时间均只给出Qt对应类型即可
在Sqlite中日期格式AAAA-BB-CC,也可以以字符串形式输入但需要保证格式正确,不建议自行转换格式
- bool SqlManager::InsertJournalSql(int catagory_id,
- QDate date,
- float value,
- QString remark,
- bool auditing) {
- QSqlQuery sql_query;//默认构造使用默认数据库
- sql_query.prepare(mInsertJournalSql);
- sql_query.bindValue(":catagory",catagory_id);
- sql_query.bindValue(":date",date);
- sql_query.bindValue(":value",value);
- sql_query.bindValue(":remark",remark);
- sql_query.bindValue(":auditing",auditing);
- if(!sql_query.exec()) {
- qDebug() << sql_query.lastError();
- return false;
- }
- return true;
- }
有返回值的操作:
- const static QString mSelectAllJournalSql =
- "select * from journal ORDER BY data DESC";//查询所有
- struct JournalStruct {
- long long id;//分类id
- QString catagory;//分类
- QString date;//日期
- float value;//值
- QString remark;//备注
- };
- QList<JournalStruct> SqlManager::SelectUnauditJournalSql(bool is_all) {
- QSqlQuery sql_query;//默认构造使用默认数据库
- if(is_all)
- sql_query.prepare(mSelectAllJournalSql);
- else
- sql_query.prepare(mSelectUnauditJournalSql);
- QList<JournalStruct> s;
- if(!sql_query.exec()) {
- qDebug() << sql_query.lastError();
- return s;
- }
- else {
- //建立类型索引
- auto cates = SelectCategorySql();
- while(sql_query.next()) {
- s.append({sql_query.value(0).toLongLong(),
- sql_query.value(1).toInt(),
- sql_query.value(2).toString(),
- sql_query.value(3).toFloat(),
- sql_query.value(4).toString()});
- }
- return s;
- }
- }
注意:QSqlQuery 结果默认指向空,必须先调用一次next()会指向第一个结果值,通过.value(0)取对应字段值,通过toXXX转换为对应格式。
详细操作代码请见流水账记录软件→GitHub
2. 其他
2.1. 多数据库情况下QSqlQuery 的使用
上述所有操作,均使用了Qt默认名称数据库,故可以直接通过 QSqlQuery XX构造实例。
若指定了特定的数据库名称,或者有多个数据库需要使用
- QSqlQuery(QSqlDatabase db);
其中db可以下面的函数获取
- static QSqlDatabase database(const QString& connectionName = QLatin1String(defaultConnection),
- bool open = true);
- QSqlQuery query(QSqlDatabase::database("connectionName"));
2.2. Qt支持的数据库
Driver Type | Description |
QDB2 | IBM DB2 |
QIBASE | Borland InterBase Driver |
QMYSQL | MySQL Driver |
QOCI | Oracle Call Interface Driver |
QODBC | ODBC Driver (includes Microsoft SQL Server) |
QPSQL | PostgreSQL Driver |
QSQLITE | SQLite version 3 or above |
QSQLITE2 | SQLite version 2 |
QTDS | Sybase Adaptive Server |
上述数据取自Qt帮助文档中QSqlDatabase的描述,其中sqlite驱动默认集成,其余数据库需要安装对应驱动否则无法使用
关于驱动的具体说明请见:SQL Database Drivers帮助文档
2.3. 建议使用QSqlQuery及bindValue操作
不建议使用qstring的arg()方法自行拼接字符串,使用bindValue可以有效的防止SQL注入。
同时此方式可读性强,也对对特殊字符具有良好的支持性。