Qt資料庫操作(qt-win-commercial-src-4.3.1,VC6,Oracle,SQL Server)

來源:互聯網
上載者:User

標籤:odbc   change   批量   rollback   cstring   設定   password   sql命令   move   

qt-win-commercial-src-4.3.1、qt-x11-commercial-src-4.3.1
Microsoft Visual C++ 6.0、KDevelop 3.5.0
Windows Xp、Solaris 10、Fedora 8
SQL Server、Oracle 10g Client

 

■、驅動編譯
這裡要提及兩個資料庫驅動,分別是ODBC和OCI

Windows作業系統中編譯ODBC驅動:
執行以下命令,會在%QTDIR%\plugins\sqldrivers目錄下面產生qsqlodbc4.dll。

cd %QTDIR%\src\plugins\sqldrivers\odbc
qmake -o Makefile odbc.pro
nmake

Unix作業系統下編譯unixODBC驅動:
unixODBC可以在http://www.unixodbc.org下載。這裡假定unixODBC安裝在/usr/local/unixODBC。
執行以下命令,會在$QTDIR/plugins/sqldrivers目錄下面產生qsqlodbc4.a。

cd $QTDIR/src/plugins/sqldrivers/odbc
qmake "INCLUDEPATH+=/usr/local/unixODBC/include" "LIBS+=-L/usr/local/unixODBC/lib -lodbc"
make

Windows作業系統中編譯OCI驅動:
這裡假定Oracle Client安裝在C:\oracle。添加oci.dll動態串連庫的環境變數c:\oracle\bin。

set INCLUDE=%INCLUDE%;c:\oracle\oci\include
set LIB=%LIB%;c:\oracle\oci\lib\msvc
cd %QTDIR%\src\plugins\sqldrivers\oci
qmake -o Makefile oci.pro
nmake

Unix作業系統下編譯OCI驅動:
當然根據你的oracle修正下相應的版本號碼。

cd $QTDIR/src/plugins/sqldrivers/oci
qmake -o Makefile "INCLUDEPATH+=/usr/include/oracle/10.1.0.3/client/" "LIBS+=-L/usr/lib/oracle/10.1.0.3/client/lib" oci.pro
make

在程式中包含標頭檔
    #include <QtSql>
在程式的.pro檔案中添加
    QT += sql


■、資料庫連接
這裡則要提及單一資料庫串連和多個資料庫連接:

單一資料庫串連:

static bool sqlConnection(const QString& HostName, 
                                         const QString& DatabaseName, 
                                         const QString& UserName, 
                                         const QString& Password)
{
    QSqlDatabase db = QSqlDatabase::addDatabase("QODBC");
    db.setHostName(HostName);
    db.setDatabaseName(DatabaseName);
    db.setUserName(UserName);
    db.setPassword(Password);

    if(!db.open())
    {
        QMessageBox::critical(0, QObject::tr("Error"), 
                                            QObject::tr("The database reported an error: %1").arg(db.lastError().text()));
        return false;
    }
    //在Qt資料庫連接後,運行"SET NAMES ‘UTF8‘"語句或"SET NAMES ‘GBK‘"。
    //db.exec("SET NAMES ‘UTF8‘");
    return true;
}

//多個資料庫連接
static bool sqlConnections()
{
    // 建立一個名為odbc的串連
    QSqlDatabase *odbc = QSqlDatabase::addDatabase( "QODBC", "ODBC" );
    if ( ! defaultDB ) {
        qWarning( "Failed to connect to odbc driver" );
        return FALSE;
    }
    odbc->setDatabaseName( DB_ODBC_DBNAME );
    odbc->setUserName( DB_ODBC_USER );
    odbc->setPassword( DB_ODBC_PASSWD );
    odbc->setHostName( DB_ODBC_HOST );
    if ( ! odbc->open() ) {
        qWarning( "Failed to open sales database: " + odbc->lastError().driverText() );
        qWarning( odbc->lastError().databaseText() );
        return FALSE;
    }

    // 建立一個名為oracle的串連
    QSqlDatabase *oracle = QSqlDatabase::addDatabase( "QOCI", "ORACLE" );
    if ( ! oracle ) {
        qWarning( "Failed to connect to oracle driver" );
        return FALSE;
    }
    oracle->setDatabaseName( DB_ORACLE_DBNAME );
    oracle->setUserName( DB_ORACLE_USER );
    oracle->setPassword( DB_ORACLE_PASSWD );
    oracle->setHostName( DB_ORACLE_HOST );
    if ( ! oracle->open() ) {
        qWarning( "Failed to open orders database: " + oracle->lastError().driverText() );
        qWarning( oracle->lastError().databaseText() );
        return FALSE;
    }

    return TRUE;
}

QSqlDatabase維護著通過addDatabase()這個靜態函數返回的的串連指標。
如果有移去一個串連,先調用QSqlDatabase::close()來關閉串連,然後通過靜態函數QSqlDatabase::removeDatabase()來移除串連。

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);
    QTextCodec::setCodecForCStrings(QTextCodec::codecForLocale());
    QTextCodec::setCodecForTr(QTextCodec::codecForLocale());
    QFont font("Times", 9, QFont::Normal, FALSE);
    app.setFont(font);

    //串連單一資料庫
    if (!sqlConnection("10.0.0.3", "qjkzdb", "sa", "syth7777"))
        return 1;

    //串連多個資料庫
    if (!sqlConnections())
        return 1;
    // 資料庫被成功開啟,得到它們的指標:
    QSqlDatabase *oracledb = QSqlDatabase::database( "ORACLE" );
    // 現在我們可以在oracle串連或預設串連上執行SQL命令
    ...

    return app.exec();
}


■、SQL執行操作

QSqlQuery提供了對資料庫記錄的Select、Insert、Update、Delete操作。

SELECT操作:

QSqlQuery query;
query.exec("SELECT name, salary FROM employee WHERE salary > 50000");
while (query.next()) {
    QString name = query.value(0).toString();
    int salary = query.value(1).toInt();
    qDebug() << name << salary;
}

通過QSqlQuery::next()、QSqlQuery::previous()、QSqlQuery::first()、QSqlQuery::last()、QSqlQuery::seek(),
可以得到下一條、上一條、第一條、最後一條、任意一條記錄的位置。

INSERT操作:

//單一插入資料
QSqlQuery query;
query.prepare("INSERT INTO employee (id, name, salary) "
                        "VALUES (:id, :name, :salary)");
query.bindValue(":id", 1001);
query.bindValue(":name", "Thad Beaumont");
query.bindValue(":salary", 65000);
query.exec();

//批量插入資料
QSqlQuery query;
query.prepare("insert into myTable values (?, ?)");

QVariantList ints;
ints << 1 << 2 << 3 << 4;
query.addBindValue(ints);
QVariantList names;
names << "Harald" << "Boris" << "Trond" << QVariant(QVariant::String);
query.addBindValue(names);

if (!query.execBatch())
    qDebug() << query.lastError();

UPDATE操作:

QSqlQuery query;
query.prepare("UPDATE employee SET salary = ? WHERE id = 1003");
query.bindValue(0, 70000);
query.exe();

DELETE操作:

QSqlQuery query;
query.exec("DELETE FROM employee WHERE id = 1007");

交易處理:

QSqlDatabase::database().transaction();
QSqlQuery query;
query.exec("SELECT id FROM employee WHERE name = ‘Torild Halvorsen‘");
if (query.next()) {
    int employeeId = query.value(0).toInt();
    query.exec("INSERT INTO project (id, name, ownerid) "
                       "VALUES (201, ‘Manhattan Project‘, "
                       + QString::number(employeeId) + ")");
}
QSqlDatabase::database().commit();

如果資料庫引擎支援交易處理,則函數QSqlDriver::hasFeature(QSqlDriver::Transactions)將返回 真。
可以通過調用QSqlDatabase::transaction()來初始化一個交易處理。之後執行你想在該交易處理的工作。
完了再執行QSqlDatabase::commit()來提交交易處理或QSqlDatabase::rollback()取消交易處理。

這裡在舉個QSqlDriver::hasFeature(QSqlDriver::QuerySize)例子,可以較快的統計查詢記錄行數。

QSqlQuery query;
int numRows;
query.exec("SELECT name, salary FROM employee WHERE salary > 50000");
QSqlDatabase defaultDB = QSqlDatabase::database();
if (defaultDB.driver()->hasFeature(QSqlDriver::QuerySize)) {
    numRows = query.size();
} else {
     // this can be very slow
     query.last();
     numRows = query.at() + 1;
}

預存程序:

AsciiToInt()是資料庫中的一個預存程序。
但我在網上以前好像看過說是SQL Server中的預存程序是通過"EXEC"完成的,而不是"CALL",這裡我不確定!留下一個疑問吧~

QSqlQuery query;
query.prepare("CALL AsciiToInt(?, ?)");
query.bindValue(0, "A");
query.bindValue(1, 0, QSql::Out);
query.exec();
int i = query.boundValue(1).toInt(); // i is 65


■、使用SQL Model類

QSqlQueryModel:一個唯讀讀取資料庫資料的模型。
QSqlTableModel:一個可讀寫的單一表格模型,可以不用寫SQL語句。
QSqlRelationalTableModel:QSqlTableModel的一個子類,可多表關聯在一起。
這些類都繼承於QAbstractTableModel,而它們又都繼承於QAbstractItemModel。

QSqlQueryModel 唯讀模式,基於SQL查詢基礎。

QSqlQueryModel model;
model.setQuery("SELECT * FROM employee");
for (int i = 0; i < model.rowCount(); ++i) {
    int id = model.record(i).value("id").toInt();
    QString name = model.record(i).value("name").toString();
    qDebug() << id << name;
}

QSqlTableModel 可對單一表操作,進行讀寫操作。

//讀取資料
QSqlTableModel model;
model.setTable("employee");
model.setFilter("salary > 50000");
model.setSort(2, Qt::DescendingOrder);
model.select();
for (int i = 0; i < model.rowCount(); ++i) {
    QString name = model.record(i).value("name").toString();
    int salary = model.record(i).value("salary").toInt();
    qDebug() << name << salary;
}
//通過QSqlTableModel::setRecord()修改資料
for (int i = 0; i < model.rowCount(); ++i) {
    QSqlRecord record = model.record(i);
    double salary = record.value("salary").toInt();
    salary *= 1.1;
    record.setValue("salary", salary);
    model.setRecord(i, record);
}
model.submitAll();
//通過QSqlTableModel::setData()來update一條記錄
model.setData(model.index(row, column), 75000);
model.submitAll();
//insert一條記錄
model.insertRows(row, 1);
model.setData(model.index(row, 0), 1013);
model.setData(model.index(row, 1), "Peter Gordon");
model.setData(model.index(row, 2), 68500);
model.submitAll();
//delete一條記錄
model.removeRows(row, 5);
model.submitAll();

函數QSqlTableModel::submitAll()確保記錄寫入資料庫中。

QSqlRelationalTableModel 通過外鍵實現了多表關聯。

//employee表中關聯city表、country表。
model->setTable("employee");
model->setRelation(2, QSqlRelation("city", "id", "name"));
model->setRelation(3, QSqlRelation("country", "id", "name"));

 

■、資料呈現視圖中

QSqlQueryModel、QSqlTableModel、QSqlRelationalTableModel一般都是藉助QListView、QTableView、QTreeView吧資料呈現出來的~
這裡我並不想對QTableView詳細講解,這裡不做過多的介紹了,也許會在以後單獨QTableView、QTableWidget詳細介紹。
資料庫部分是這次的重點!
繼續在對QSqlRelationalTableModel這個作以講解補充,因為上面提及的實在太少了。

QSqlRelationalTableModel model;
model->setTable("employee");
model->setRelation(2, QSqlRelation("city", "id", "name"));
model->setRelation(3, QSqlRelation("country", "id", "name"));
//設定標題頭部標籤資訊
model->setHeaderData(0, Qt::Horizontal, QObject::tr("ID"));
model->setHeaderData(1, Qt::Horizontal, QObject::tr("Name"));
model->setHeaderData(2, Qt::Horizontal, QObject::tr("City"));
model->setHeaderData(3, Qt::Horizontal, QObject::tr("Country"));
//值得注意的是,在查詢時應該明確指明那個表的資料資訊,以下兩種方式是等價的。
model.setFilter(tr("city.name = ‘%1‘").arg("Mucich"));
//model.setFilter(tr("employee.cityid = %1").arg(312));
model.select();
//藉助QTableView,把資料資訊顯示出來,
QTableView *view = new QTableView;
view->setModel(model);
//將表中的項,設計為不能編輯模式
view->setEditTriggers(QAbstractItemView::NoEditTriggers);
view->show();

在將一種通過QSqlField進行Insert、Update、Delete的操作。上邊的例子,繼續~

QSqlField idField("id", QVariant::Int);
QSqlField nameField("name", QVariant::String);
QSqlField cityIdField("cityId", QVariant::Int);
QSqlField countryIdField("countryId", QVariant::Int);

//一條記錄 Id = 12、Name = vic.MINg、City = ShenYang、Country = China。(瀋陽區號024、中國086)
idField.setValue(12);
nameField.setValue("vic.MINg");
cityIdField.setValue(24);
countryIdField.setValue(86);

//insert一條記錄,-1表示在最尾端加入
QSqlRecord record;
record.append(idField);
record.append(nameField);
record.append(cityIdField);
record.append(countryIdField);
model->insertRecord(-1, record);

//update一條記錄, row表示要修改的行
QSqlRecord record = model->record(row);
record.replace(1, nameField);
record.replace(2, cityIdField);
record.replace(3, countryIdField);
model->setRecord(row, record);

//delete一條記錄, row表示要修改的行
model->removeRow(row);


■、資料呈現表單中

通過QDataWidgetMapper可以在表單控制項與資料庫中的記錄關聯在一起。

QDataWidgetMapper *mapper = new QDataWidgetMapper;
mapper->setModel(model);
mapper->addMapping(idSpinBox, 0);
mapper->addMapping(nameLineEdit, 1);
mapper->addMapping(cityComboBox, 2);
mapper->addMapping(countryComboBox, 3);
//可以通過toFirst()、toNext()、toPrevious()、toLast()、setCurrentIndex()來設定目前記錄位置,顯示相應資料
mapper->toFirst();
//訊號、槽的機制model、view、mapper三個聯絡再一起
connect(view->selectionModel(), SIGNAL(currentRowChanged(QModelIndex,QModelIndex)), 
        mapper, SLOT(setCurrentModelIndex(QModelIndex)));

 

http://cool.worm.blog.163.com/blog/static/64339006200833024214394/

Qt資料庫操作(qt-win-commercial-src-4.3.1,VC6,Oracle,SQL Server)

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.