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)的更多相关文章

  1. Oracle,SQL Server 数据库较MySql数据库,Sql语句差异

    原文:Oracle,SQL Server 数据库较MySql数据库,Sql语句差异 Oracle,SQL Server 数据库较MySql数据库,Sql语句差异 1.关系型数据库 百度百科 关系数据库 ...

  2. 介绍几种大型的Oracle/SQL Server数据库免费版

    我们知道,Oracle和SQL Server等大型数据库也都存在一些免费的版本,这些免费的版本已经能够满足许多中小项目的需求.对于在校大学生来说,从学习的目标上来讲,安装免费版的大型数据库也就足够用了 ...

  3. mysql,oracle,sql server数据库默认的端口号,端口号可以为负数吗?以及常用协议所对应的缺省端口号

    mysql,oracle,sql server数据库默认的端口号? mysql:3306 Oracle:1521 sql server:1433 端口号可以为负吗? 不可以,端口号都有范围的,0~65 ...

  4. 2.大约QT数据库操作,简单的数据库连接操作,增删改查数据库,QSqlTableModel和QTableView,事务性操作,大约QItemDelegate 代理

     Linux下的qt安装,命令时:sudoapt-get install qt-sdk 安装mysql数据库,安装方法參考博客:http://blog.csdn.net/tototuzuoquan ...

  5. Qt: 数据库操作;

    QT的数据库操作有两种方式: 一) 使用QsqlTableModel类, 可以配合QTableView进行界面显示并进行数据库操作, 这种方法比较方便快捷: 二)  使用原始SQL语言, 利用INSE ...

  6. qt 数据库操作总结

    #include <QtSql>QT += sql QSqlDatabase类实现了数据库连接的操作QSqlQuery类用来执行SQL语句QSqlRecord类 封装数据库所有记录 第一: ...

  7. 转:不在同一个服务器上的数据库之间的数据操作(oracle/sql server的对比)

    如何操做不在同一个数据库中的数据操作: 一.对于SQL server来讲:  1.采用创建链接服务器的方式:    (1).创建链接服务器       exec sp_addlinkedserver  ...

  8. Perl/C#连接Oracle/SQL Server和简单操作

    连接数据库是一个很常见也很必须的操作.先将我用到的总结一下. 1. Perl 连接数据库 Perl 连接数据库的思路都是: 1)使用DBI模块: 2)创建数据库连接句柄dbh: 3)利用dbh创建语句 ...

  9. sqlserver2008创建数据库 报 Cannot read property is filestream 此属性不可用于sql server 7.0 解决

    在创建数据库的时候,报整个错误 Cannot read property is filestream 此属性不可用于sql server 7.0 按照网上的方法  (http://blog.csdn. ...

随机推荐

  1. HealthKit开发教程之HealthKit的主要类型数据

    HealthKit开发教程之HealthKit的主要类型数据 在HealthKit中,我们将最常用到的数据称之为主要数据.主要数据基本上有三种:长度类型的数据.质量类型的数据.能量类型的数据.本节将主 ...

  2. 移动APP 中文输入法下的搜索优化

    最近做了一个移动端的搜索功能,带有suggest.实现上并没有什么可说的,但是在后续优化上,特别是在中文输入法的情况下的优化使我学到一些新东西,所以决定写一篇文章. 下面是我简化后的基本功能实现,监听 ...

  3. 洛谷 P2024 食物链 POJ 1182 Label:并查集Turbo

    题目描述 动物王国中有三类动物 A,B,C,这三类动物的食物链构成了有趣的环形.A 吃 B,B 吃 C,C 吃 A. 现有 N 个动物,以 1 - N 编号.每个动物都是 A,B,C 中的一种,但是我 ...

  4. 洛谷 P1010 幂次方 Label:模拟

    题目描述 任何一个正整数都可以用2的幂次方表示.例如 137=2^7+2^3+2^0 同时约定方次用括号来表示,即a^b 可表示为a(b). 由此可知,137可表示为: 2(7)+2(3)+2(0) ...

  5. TYVJ P1075 硬币游戏 Label:dp

    背景 农民John的牛喜欢玩硬币,所以John就为它们发明了一个新的两人硬币游戏,叫做Xoinc. 描述 最初地面上有一堆n个硬币(5<=n<=2000),从上面数第i个硬币的价值为C_i ...

  6. 【wikioi】1295 N皇后问题

    题目链接 算法:DFS 刚开始卡了我一下,我竟然傻到用二维来放皇后= =.导致一直TLE.... 其实用1维就行了的,下标为行(列),值为列(行) 我是用下标为列做的. 上代码 #include &l ...

  7. Chromium的GPU进程启动流程

    转载请注明出处:http://www.cnblogs.com/fangkm/p/3960327.html 硬件渲染依赖计算机的GPU,GPU种类繁多,兼容这么多种类的硬件,稳定性是个大问题,虽然Chr ...

  8. BZOJ3211 花神游历各国

    Description   Input   Output 每次x=1时,每行一个整数,表示这次旅行的开心度 Sample Input 4 1 100 5 5 5 1 1 2 2 1 2 1 1 2 2 ...

  9. Redis内存存储结构分析

    1 Redis 内存存储结构 本文是基于 Redis-v2.2.4 版本进行分析. 1.1 Redis 内存存储总体结构 Redis 是支持多key-value数据库(表)的,并用 RedisDb 来 ...

  10. Java实现FTP文件上传与下载

    实现FTP文件上传与下载可以通过以下两种种方式实现(不知道还有没有其他方式),分别为:1.通过JDK自带的API实现:2.通过Apache提供的API是实现. 第一种方式 package com.cl ...