博客地址已更改,文章數量較多不便批量修改,若想訪問源文請到 coologic博客 查閱,網址:www.coologic.cn
如本文記錄地址為 techieliang.com/A/B/C/ 請改為 www.coologic.cn/A/B/C/ 即可查閱
版權聲明:若無來源注明, Techie亮博客文章均為原創。 轉載請以鏈接形式標明本文標題和地址:
本文標題: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注入。
同時此方式可讀性強,也對對特殊字符具有良好的支持性。