1. 程式人生 > >QT讀寫Sqlite資料庫的三種方式

QT讀寫Sqlite資料庫的三種方式

     QT對一些基本的資料庫的訪問封裝,可謂是極大的方便的我們開發人員,現在我們就來說下QT對Sqlite這個資料庫的讀寫,Sqlite是一個比較小型的本地資料庫,對於儲存一些軟體配置引數或量不是很大的資料是相當的方便,Qt本身已經自帶了Sqlite的驅動,直接使用相關的類庫即可,這篇我們主要來說明QT訪問Sqlite資料庫的三種方式(即使用三種類庫去訪問),分別為QSqlQuery、QSqlQueryModel、QSqlTableModel,對於這三種類庫,可看為一個比一個上層,也就是封裝的更厲害,甚至第三種QSqlTableModel,根本就不需要開發者懂SQL語言,也能操作Sqlite資料庫。

1、首先使用QSqlQuery來訪問
      我們先要在工程中包含與資料庫相關的幾個標頭檔案#include <QtSql/QSqlDatabase> 、#include <QtSql/QSqlRecord>、#include <QtSql/QSqlQuery>
訪問的資料庫內容結構為:

#include <QtWidgets/QApplication>
#include <QCoreApplication>
#include <QDebug>

#include <QtSql/QSqlDatabase>
#include <QtSql/QSqlQuery>
#include <QtSql/QSqlRecord>

typedef struct _testInfo //假定資料庫儲存內容
{
    QString UsreName;
    QString IP;
    QString Port;
    QString PassWord;
    QString Type;

}testInfo;

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    QVector<testInfo> infoVect; //testInfo向量,用於儲存資料庫查詢到的資料

    QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");  

    db.setDatabaseName(QApplication::applicationDirPath() + "/CONFIG/" + "CONFIG.db");
    if (!db.open())
    {
    	return 0;
    }

/**************************使用QSqlQuery操作資料庫**************************/
    QSqlQuery query;	//執行操作類物件

    //查詢資料
    query.prepare("SELECT * FROM T_USER_MANAGE");
    query.exec();	//執行
	
    QSqlRecord recode = query.record();		//recode儲存查詢到一些內容資訊,如表頭、列數等等
    int column = recode.count();			//獲取讀取結果的列數	
    QString s1 = recode.fieldName(0);		//獲取第0列的列名

    while (query.next())
    {
	    testInfo tmp;
	    tmp.UsreName = query.value("UsreName").toString();
	    tmp.IP = query.value("IP").toString();
	    tmp.Port = query.value("Port").toString();
	    tmp.PassWord = query.value("PassWord").toString();
	    tmp.Type = query.value("Type").toString();

	    infoVect.push_back(tmp);   //將查詢到的內容存到testInfo向量中
    }

    for (int i=0; i<infoVect.size(); i++)    //列印輸出
    {
	    qDebug() << infoVect[i].UsreName << ":"	\
	             << infoVect[i].IP << ":"		\
		         << infoVect[i].Port << ":"		\
		         << infoVect[i].PassWord << ":" \
		         << infoVect[i].Type;
	}
	
	//插入資料
    query.prepare("INSERT INTO T_USER_MANAGE (UsreName, IP, Port, PassWord, Type) VALUES (:UsreName, :IP, :Port, :PassWord, :Type)");
    query.bindValue(":UserName", "user4");	//給每個插入值識別符號設定具體值
    query.bindValue(":IP", "192.168.1.5");
    query.bindValue(":Port", "5004");
    query.bindValue(":PassWord", "55555");
    query.bindValue(":Type", "operator");
    query.exec();	


    //更改表中 UserName=user4 的Type屬性為admin
    query.prepare("UPDATE T_USER_MANAGE SET Type='admin' WHERE UserName='user4'");
    query.exec();

    //刪除表中 UserName=user4的使用者資訊
    query.prepare("DELETE FROM T_USER_MANAGE WHERE UserName='user4'");
    query.exec();

#endif
/**************************使用QSqlQuery操作資料庫END***********************/

編譯輸出:

2、使用QSqlQueryModel來訪問

 QSqlQueryModel類帶有Model字樣,相信你已經猜到我們可以用他來關聯試圖,就能把資料庫的內容顯示到檢視上,當然,常規的操作也是可以的,但是我們只說說怎麼用這個類來把資料庫中的內容顯示到是檢視中,這裡我們選擇的檢視類為QTableView,直接上程式碼吧
 

#include <QtWidgets/QApplication>
#include <QCoreApplication>
#include <QDebug>
#include <QString>
#include <QTableView>

#include <QtSql/QSqlDatabase>
#include <QtSql/QSqlQueryModel>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");

    db.setDatabaseName(QApplication::applicationDirPath() + "/CONFIG/" + "CONFIG.db");
    if (!db.open())
    {
    	return 0;
    }

    QSqlQueryModel *model = new QSqlQueryModel;
    model->setQuery("SELECT * FROM T_USER_MANAGE", db);	//從給定的資料庫db執行sql操作, db需預先制定並開啟
	
    int column = model->columnCount();	//獲取列數
    int row = model->rowCount();		//獲取行數

    model->setHeaderData(0, Qt::Horizontal, QStringLiteral("使用者名稱"));	//設定表頭,如不設定則使用資料庫中的預設表頭
    model->setHeaderData(1, Qt::Horizontal, QStringLiteral("IP地址"));
    model->setHeaderData(2, Qt::Horizontal, QStringLiteral("埠"));
    model->setHeaderData(3, Qt::Horizontal, QStringLiteral("密碼"));
    model->setHeaderData(4, Qt::Horizontal, QStringLiteral("使用者型別"));

    QTableView *view = new QTableView;	//定義檢視,只能用於顯示,不能修改資料庫
    view->setFixedSize(500, 200);
    view->setModel(model);

    view->show();

    return a.exec();
}

編譯執行一下:

3、最後使用QSqlTableModel來訪問
      最後我們來說說使用QSqlTableModel這個類去操作Sqlite資料庫,這個類比上兩個封裝的更徹底,即使我們不懂SQL語言,也能實現對Sqlite資料庫的操作,並且這個類也可以通過檢視來顯示修改資料庫內容,這裡我就拿這個類做了個使用者管理模組,其實也可以通用與其他任何一個模組,只要在生成物件時傳入sqlite的資料庫名及要操作的表名即可。

    在這個例子中,我實現了一個KSDemoDlg類,其實是一個對話方塊類,裡邊包含了sqlite資料庫的顯示、修改等等功能,首先來看下效果(常規的增刪改查功能都有):

當我們點選增加、修改時,右邊的編輯框便為可編輯狀態(說明下,右邊的編輯框是隨著載入的資料庫表變化而變化的,簡而言之就是可以不做修改就能操作別的Sqlite資料庫),完畢確定後便寫進資料庫,同時也在左邊的表格中顯示

標頭檔案:

#ifndef __KSDEMODLG_H__
#define __KSDEMODLG_H__

#include <QDialog>
#include <QPushButton>
#include <QLineEdit>
#include <QLabel>
#include <QComboBox>
#include <QGroupBox>
#include <QTableView>
#include <QtSql/QSqlTableModel>
#include <QtSql/QSqlDatabase>


class KSDemoDlg : public QDialog
{
    Q_OBJECT

    enum {UPDATE, INSERT};
    int m_operator;

public:
    explicit KSDemoDlg(QString databaseName, QString dataTableName, QWidget *parent = 0 );
    ~KSDemoDlg();

private:
	
    void UiInit(); 

protected slots:
    void onNewButtonClicked();
    void onQueryButtonClicked();
    void onUpdateButtonClicked();
    void onDeleteButtonClicked();
    void onPrimaryKeyLineEditEmpty(const QString & text);
    void onCurrentTableViewClicked(const QModelIndex & index);
    void onOKButtonClicked();
    void onCancelButtonClicked();

private:
    QSqlDatabase m_db;
    QString m_DBName;
    QString m_DBTableName;

private:
    QTableView* m_TabView;
    QSqlTableModel* m_model;

private:
    QList<QLineEdit*> m_infoEditList;
    QList<QLabel*> m_infoLabelList;
    QPushButton m_OKButton;
    QPushButton m_CancelButton;

private:

    /*所有使用者資訊容器組*/
    QGroupBox m_Group;

    QLabel m_PrimaryKeyLabel;
    QLineEdit m_PrimaryKeyLineEdit;
    QPushButton m_QueryButton;

    QPushButton m_NewButton;	
    QPushButton m_UpdateButton;
    QPushButton m_DeleteButton;

    /*所選擇使用者資訊容器組*/
    QGroupBox m_SelectGroup;
	
};

#endif // __KSDEMODLG_H__

.cpp檔案
 

#include <QtWidgets/QApplication>
#include <QCoreApplication>
#include <QString>
#include <QFormLayout>
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QMessageBox>
#include <QtSql/QSqlRecord>
#include <QDebug>

#include "KSDemoDlg.h"
  

/**************************************************************************
* 函式名稱:KSDemoDlg
* 函式功能:使用者管理對話方塊建構函式
* 輸入引數:無
* 輸出引數:無
* 返回數值:void
* 建立人員:
* 建立時間:2017-11-15
* 修改人員:
* 修改時間:
**************************************************************************/
KSDemoDlg::KSDemoDlg(QString databaseName, QString dataTableName, QWidget *parent):QDialog(parent, Qt::WindowCloseButtonHint | Qt::WindowMinMaxButtonsHint | Qt::WindowStaysOnTopHint),
	m_Group(this), m_PrimaryKeyLabel(this), m_PrimaryKeyLineEdit(this), m_QueryButton(this), m_NewButton(this), m_UpdateButton(this), m_DeleteButton(this), m_TabView(NULL),m_model(NULL),
	m_OKButton(this),m_CancelButton(this), m_DBName(databaseName), m_DBTableName(dataTableName), m_operator(-1)
{
    //開啟資料庫

    m_db = QSqlDatabase::addDatabase("QSQLITE");
    m_db.setDatabaseName(QApplication::applicationDirPath() + "/config/" + databaseName);
    if (!m_db.open())
    {
    	m_DBName = "";
    	m_DBTableName = "";
    }

    m_model = new QSqlTableModel(this, m_db);
    m_model->setTable(m_DBTableName);
    m_model->setEditStrategy(QSqlTableModel::OnManualSubmit); //手動提交後才修改

    m_model->select();

    m_TabView = new QTableView(this);
    m_TabView->setEditTriggers(QAbstractItemView::NoEditTriggers);	//設定內容不可編輯

    /*************關聯槽函式*********************/
    connect(&m_NewButton, SIGNAL(clicked()), this, SLOT(onNewButtonClicked()));
    connect(&m_QueryButton, SIGNAL(clicked()), this, SLOT(onQueryButtonClicked()));
    connect(&m_UpdateButton, SIGNAL(clicked()), this, SLOT(onUpdateButtonClicked()));
    connect(&m_DeleteButton, SIGNAL(clicked()), this, SLOT(onDeleteButtonClicked()));
    connect(&m_PrimaryKeyLineEdit, SIGNAL(textChanged(const QString &)), this, SLOT(onPrimaryKeyLineEditEmpty(const QString &)));
    connect(m_TabView, SIGNAL(clicked(const QModelIndex &)), this, SLOT(onCurrentTableViewClicked(const QModelIndex &)));
    connect(&m_OKButton, SIGNAL(clicked()), this, SLOT(onOKButtonClicked()));
    connect(&m_CancelButton, SIGNAL(clicked()), this, SLOT(onCancelButtonClicked()));

    /*************模型關聯檢視*******************/

    m_TabView->setModel(m_model);

    /*************選中行為為整行選中*************/
    m_TabView->setSelectionBehavior(QAbstractItemView::SelectRows);	

    /*************對話方塊窗體初始化***************/
    UiInit(); 

    /*************對話方塊窗體初始化***************/
    setFixedSize(600, 400);
    setWindowTitle(QStringLiteral("使用者管理"));
}

/**************************************************************************
* 函式名稱:UiInit
* 函式功能:使用者管理對話方塊介面初始化
* 輸入引數:無
* 輸出引數:無
* 返回數值:void
* 建立人員:
* 建立時間:2017-11-15
* 修改人員:
* 修改時間:
**************************************************************************/

void KSDemoDlg::UiInit()
{
    m_PrimaryKeyLabel.setText(m_model->headerData(0, Qt::Horizontal).toString());
    m_NewButton.setText(QStringLiteral("增加"));
    m_QueryButton.setText(QStringLiteral("查詢"));
    m_UpdateButton.setText(QStringLiteral("修改"));
    m_DeleteButton.setText(QStringLiteral("刪除"));
    m_UpdateButton.setEnabled(true);

    m_OKButton.setText(QStringLiteral("確定"));
    m_CancelButton.setText(QStringLiteral("取消"));

    /**************靈活增加介面右側資料顯示形式******************/
    for(int i=0; i<m_model->columnCount(); i++)
    {
    	m_infoLabelList.append(new QLabel(this));
    	m_infoLabelList[i]->setText(m_model->headerData(i, Qt::Horizontal).toString());

    	m_infoEditList.append(new QLineEdit(this));
    	m_infoEditList[i]->setEnabled(false);
    }
    m_OKButton.setEnabled(false);
    m_CancelButton.setEnabled(false);

    /**************靈活增加介面右側資料顯示形式 END******************/

    QHBoxLayout *TotalHBoxLayout = new QHBoxLayout();
    QVBoxLayout *TotalVBoxLayout = new QVBoxLayout();

    QVBoxLayout *UserGroupVBoxLayout = new QVBoxLayout();

    QHBoxLayout *UserEditHBoxLayout = new QHBoxLayout();
    QHBoxLayout *UserButtonHBoxLayout = new QHBoxLayout();

    QFormLayout *UserPrimaryKeyFormLayout = new QFormLayout();

    QFormLayout *UserSelectFormLayout = new QFormLayout();
    QHBoxLayout *UserSelectHBoxLayout = new QHBoxLayout();
    QVBoxLayout *UserSelectVBoxLayout = new QVBoxLayout();

    /*****************介面右側group佈局******************/
    for (int i=0; i<m_infoLabelList.count(); i++)
    {
    	UserSelectFormLayout->addRow( m_infoLabelList[i], m_infoEditList[i]);
    }
    UserSelectHBoxLayout->addWidget(&m_OKButton);
    UserSelectHBoxLayout->addWidget(&m_CancelButton);

    UserSelectVBoxLayout->addLayout(UserSelectFormLayout);
    UserSelectVBoxLayout->addLayout(UserSelectHBoxLayout);
    UserSelectVBoxLayout->addStretch();

    /*****************介面右側group佈局 END******************/
	
    UserPrimaryKeyFormLayout->addRow(&m_PrimaryKeyLabel, &m_PrimaryKeyLineEdit); 

    UserEditHBoxLayout->addLayout(UserPrimaryKeyFormLayout);
    UserEditHBoxLayout->addWidget(&m_QueryButton);
    UserEditHBoxLayout->addStretch();
	
    UserButtonHBoxLayout->addWidget(&m_NewButton);
    UserButtonHBoxLayout->addWidget(&m_UpdateButton);
    UserButtonHBoxLayout->addWidget(&m_DeleteButton);

    UserGroupVBoxLayout->addLayout(UserEditHBoxLayout);
    UserGroupVBoxLayout->addLayout(UserButtonHBoxLayout);

    m_Group.setLayout(UserGroupVBoxLayout);

    TotalVBoxLayout->addWidget(&m_Group);
    TotalVBoxLayout->addWidget(m_TabView);

    TotalHBoxLayout->addLayout(TotalVBoxLayout, 3);
    TotalHBoxLayout->addLayout(UserSelectVBoxLayout, 1);

    setLayout(TotalHBoxLayout);
}

/**************************************************************************
* 函式名稱:onNewUserButtonClick
* 函式功能:使用者管理對話方塊界新增使用者按鈕槽函式
* 輸入引數:無
* 輸出引數:無
* 返回數值:void
* 建立人員:
* 建立時間:2017-11-15
* 修改人員:
* 修改時間:
**************************************************************************/
void KSDemoDlg::onNewButtonClicked()
{
    for (int i=0; i<m_infoEditList.count(); i++)
    {
    	m_infoEditList[i]->setEnabled(true);
    }
    m_operator = INSERT;
    m_OKButton.setEnabled(true);
    m_CancelButton.setEnabled(true);
}

/**************************************************************************
* 函式名稱:onQueryUserButtonClick
* 函式功能:使用者管理對話方塊界查詢使用者按鈕槽函式
* 輸入引數:無
* 輸出引數:無 
* 返回數值:void
* 建立人員:廖明勝
* 建立時間:2017-11-15
* 修改人員:
* 修改時間:
**************************************************************************/
void KSDemoDlg::onQueryButtonClicked()
{
    QString toFind = m_PrimaryKeyLineEdit.text();

    QString ID = m_model->headerData(0, Qt::Horizontal).toString();

    m_model->setFilter(ID + "=\'" + toFind + "\'");

    m_model->select();
}

/**************************************************************************
* 函式名稱:onUpdateButtonClicked
* 函式功能:使用者管理對話方塊界修改使用者按鈕槽函式
* 輸入引數:無
* 輸出引數:無
* 返回數值:void
* 建立人員:
* 建立時間:2017-11-15
* 修改人員:
* 修改時間:
**************************************************************************/
void KSDemoDlg::onUpdateButtonClicked()
{
    int toUpdate = m_TabView->currentIndex().row();

    QSqlRecord recode = m_model->record(toUpdate);

    for (int i=0; i<recode.count(); i++)
    {
    	m_infoEditList[i]->setEnabled(true);
    	m_infoEditList[i]->setText(recode.value(i).toString());
    }
    m_operator = UPDATE;
    m_OKButton.setEnabled(true);
    m_CancelButton.setEnabled(true);
	
}

/**************************************************************************
* 函式名稱:onDeleteButtonClicked
* 函式功能:使用者管理對話方塊界刪除使用者按鈕槽函式
* 輸入引數:無
* 輸出引數:無
* 返回數值:void
* 建立人員:
* 建立時間:2017-11-15
* 修改人員:
* 修改時間:
**************************************************************************/
void KSDemoDlg::onDeleteButtonClicked()
{
    int toDelRow = m_TabView->currentIndex().row();

    if (QMessageBox::Ok == QMessageBox::warning(this, QStringLiteral("提示"), QStringLiteral("確定要刪除") + m_model->data(m_model->index(toDelRow, 0)).toString() + QStringLiteral("嗎?"), QMessageBox::Ok|QMessageBox::No))
    {
    	m_model->removeRow(toDelRow);
    	m_model->submitAll();
    }
	
    m_model->select();
}

/**************************************************************************
* 函式名稱:onUserNameEditEmpty
* 函式功能:當m_UserNameEdit編輯框為空時,顯示所有使用者
* 輸入引數:無
* 輸出引數:無
* 返回數值:void
* 建立人員:
* 建立時間:2017-11-15
* 修改人員:
* 修改時間:
**************************************************************************/
void KSDemoDlg::onPrimaryKeyLineEditEmpty(const QString & text)
{
    if (text.isEmpty())
    {
    	m_model->setTable(m_DBTableName);	//重新關聯資料庫表,這樣才能查詢整個表
    	m_model->select();
    }
}

/**************************************************************************
 * 函式名稱:onCurrentTableViewActived
 * 函式功能:m_TableView檢視選取當前行槽函式,內容對映到右側使用者編輯中
 * 輸入引數:無
 * 輸出引數:無
 * 返回數值:void
 * 建立人員:
 * 建立時間:2017-11-15
 * 修改人員:
 * 修改時間:
 **************************************************************************/
void KSDemoDlg::onCurrentTableViewClicked(const QModelIndex & index)
{
    if (!m_OKButton.isEnabled() || (INSERT == m_operator))	//只有可編輯並且操作為修改操作時才對映內容
    {
    	return;
    }

    int currentRow = index.row();

    QSqlRecord recode = m_model->record(currentRow);

    for (int i=0; i<recode.count(); i++)
    {
    	m_infoEditList[i]->setEnabled(true);
    	m_infoEditList[i]->setText(recode.value(i).toString());
    }
}

/**************************************************************************
 * 函式名稱:onOKButtonClicked
 * 函式功能:OKButton點選槽函式,確定修改資料庫
 * 輸入引數:無
 * 輸出引數:無
 * 返回數值:void
 * 建立人員:
 * 建立時間:2017-11-15
 * 修改人員:
 * 修改時間:
 **************************************************************************/
void KSDemoDlg::onOKButtonClicked()
{
    for (int i=0; i<m_infoEditList.count(); i++)
    {
    	if (m_infoEditList[i]->text().isEmpty())
    	{
    		QMessageBox::warning(this, QStringLiteral("提示"), QStringLiteral("請將內容填寫完整"), QMessageBox::Ok);
    		return;
    	}
    }

    switch (m_operator)
    {
    case INSERT:
    	{
    		if (QMessageBox::Ok == QMessageBox::warning(this, QStringLiteral("提示"), QStringLiteral("請確定是否增加"), QMessageBox::Ok|QMessageBox::No))
    		{
    			int col = m_model->columnCount();
    			int row = m_model->rowCount();
    			m_model->insertRow(row);
    			for (int i=0; i<col; i++)
    			{
			        m_model->setData(m_model->index(row, i), m_infoEditList[i]->text());
		        }

		        m_model->submitAll();	//提交修改
		    }
	    }
	    break;
    case UPDATE:
    	{
    		if (QMessageBox::Ok == QMessageBox::warning(this, QStringLiteral("提示"), QStringLiteral("請確定是否修改"), QMessageBox::Ok|QMessageBox::No))
    		{
    			int col = m_model->columnCount();
    			int CurrentRow = m_TabView->currentIndex().row();
    			for (int i=0; i<col; i++)
    			{
    				m_model->setData(m_model->index(CurrentRow, i), m_infoEditList[i]->text());
    			}

    			m_model->submitAll();	//提交修改
    		}
    	}
    	break;
    default:
    	break;
    }

    for (int i=0; i<m_infoEditList.count(); i++)
    {
    	m_infoEditList[i]->setText("");
    	m_infoEditList[i]->setEnabled(false);
    }

    m_model->select();
    m_OKButton.setEnabled(false);
    m_CancelButton.setEnabled(false);
}

/**************************************************************************
* 函式名稱:onCancelButtonClicked
* 函式功能:OKButton點選槽函式,不操作
* 輸入引數:無
* 輸出引數:無
* 返回數值:void
* 建立人員:
* 建立時間:2017-11-15
* 修改人員:
* 修改時間:
**************************************************************************/
void KSDemoDlg::onCancelButtonClicked()
{
    for (int i=0; i<m_infoEditList.count(); i++)
    {
    	m_infoEditList[i]->setText("");
    	m_infoEditList[i]->setEnabled(false);
    }
    m_OKButton.setEnabled(false);
    m_CancelButton.setEnabled(false);
}

/**************************************************************************
* 函式名稱:~KsUserManageDlg
* 函式功能:使用者管理對話方塊解構函式
* 輸入引數:無
* 輸出引數:無
* 返回數值:void
* 建立人員:
* 建立時間:2017-11-15
* 修改人員:
* 修改時間:
**************************************************************************/

KSDemoDlg::~KSDemoDlg()
{
    qDebug() << "KSDemoDlg::~KSDemoDlg()";
    m_db.close();
}

main函式
 

#include "KsTestDemo.h"
#include <QtWidgets/QApplication>
#include <QCoreApplication>

#include "KSDemoDlg.h"

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    KSDemoDlg dlg("CONFIG.db", "T_USER_MANAGE");    //這裡我們在生成KSDemoDlg類的時候,在建構函式中傳入sqlite資料庫名CONFIG.DB和想要操作的表T_USER_MANAGE

    dlg.show();    //顯示一下就OK
    return a.exec();
}

上邊的 KSDemoDlg dlg("CONFIG.db", "T_USER_MANAGE");資料庫名跟表也可以換成其他的,程式碼通用。