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 客户端
■、驱动编译
这里要提一下两个数据库驱动,分别是ODBC和OCI
在Windows操作系统中编译ODBC驱动程序:
执行以下命令,将在%QTDIR%\plugins\sqldrivers目录下生成qsqlodbc4.dll。
cd %QTDIR%\src\plugins\sqldrivers\odbc
qmake -o Makefile www.sychzs.cn
nmake
在Unix操作系统下编译unixODBC驱动程序:
unixODBC可以从http://www.sychzs.cn下载。这里假设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。
设置 INCLUDE=%INCLUDE%;c:\oracle\oci\include
设置 LIB=%LIB%;c:\oracle\oci\lib\msvc
cd %QTDIR%\src\plugins\ sqldrivers\oci
qmake -o Makefile www.sychzs.cn
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"www.sychzs.cn
make
在程序中包含头文件
#include
在程序的.pro文件中添加
QT += sql
■、数据库连接
这里不得不提一下单数据库连接和多数据库连接:
单个数据库连接:
static bool sqlConnection(const QString& HostName,
const QString& DatabaseName,
const QString& 用户名,
const QString& 密码)
{
QSqlDatabase db = QSqlDatabase::addDatabase("QODBC" );
db.setHostName(主机名);
db.setDatabaseName(数据库名称);
db.setUserName(用户名);
db.setPassword(密码);if(!www.sychzs.cn())
? , " ODBC" );
{
QMessageBox::ritic(0, QObject::tr("错误"),
QObject::tr("数据库报错: %1").arg(db.lastError().text()));
return false;
}
//在Qt数据库连接后,运行"SET NAMES 'UTF8'"语句或"SET NAMES 'GBK'"。
//db.exec("SET NAMES 'UTF8'");
return true;
}
if ( !defaultDB ) {
qWarning( "无法连接到 odbc 驱动程序" );
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("打开销售数据库失败:" + odbc->lastError().driverText());//创建名为oracle的连接
QSqlDatabase *oracle = QSqlDatabase::addDatabase( "QOCI", "ORACLE" );无法连接到 oracle 驱动程序" );
return FALSE;
oracle->setPassword( DB_ORACLE_PASSWD );
oracle->setHostName( DB_ORACLE_HOST ); if ( !oracle->open() ) {
qWarning( "无法打开订单数据库:" + oracle->lastError().driverText() ) ;
qWarning( oracle->lastError().databaseText() );返回 TRUE;
}
QSqlDatabase 维护静态函数 addDatabase() 返回的连接指针。
如果删除连接,首先调用 QSqlDatabase::close() 关闭连接,然后使用静态函数 QSqlDatabase::removeDatabase() 删除连接。
int main(int argc, char *argv[])
? ? SqlDatabase::database( "ORACLE" );
{
QApplication app(argc, argv);
QTextCodec::setCodecForCStrings(QTextCodec::codecForLocale());
QTextCodec ::setCodecForTr(QTextCodec::codecForLocale());
QFont 字体("Times", 9, QFont::Normal, FALSE);
app.setFont(font);
// 现在我们可以在 oracle 连接或默认连接上执行 SQL 命令
...return app.exec();
}
■、SQL执行操作
QSqlQuery 提供数据库记录的选择、插入、更新和删除操作。
选择操作:
QSqlQuery查询;
query.exec("从员工中选择姓名,工资,工资> 50000");
while (www.sychzs.cn()) {
QString name = query.value(0 ).toString();
int 工资 = query.value(1).toInt();
qDebug() << 姓名 << 工资;
}
通过QSqlQuery::next()、QSqlQuery::previous()、QSqlQuery::first()、QSqlQuery::last()、QSqlQuery::seek(),
可以获取下一个、上一个、和第一个、最后一个和任何记录的位置。
INSERT操作:
//单个插入数据
QSqlQuery查询;
query.prepare("INSERT INTO员工(id,name,salary)"
"VALUES(:id,:name,:salary)" ) ;
query.bindValue(":id", 1001);
query.bindValue(":name", "萨德·博蒙特");
query.bindValue(":salary", 65000);
query.exec();//批量插入数据
QSqlQuery查询;
query.prepare("insert into myTable values(?, ?)");QVariantList 整数;
ints << 1 << 2 << 3 << 4;
query.addBindValue(ints);
QVariantList 名称;
名称 << "Harald" << "鲍里斯" << "Trond" << QVariant(QVariant::String);
query.addBindValue(names);if (!query.execBatch())
qDebug() << query.lastError();
更新操作:
QSqlQuery 查询;
query.prepare("更新员工设置工资 = ? WHERE id = 1003");
query.bindValue(0, 70000);
query.exe();
删除操作:
QSqlQuery 查询;
query.exec("从员工 WHERE id = 1007 中删除");
事务处理:
QSqlDatabase::database().transaction();
QSqlQuery 查询;
query.exec("从员工中选择 id WHERE name = 'Torild Halvorsen'");
if (www.sychzs.cn ()) {
int employeeId = query.value(0).toInt();
query.exec("INSERT INTO 项目 (id, name, Ownerid)"
"VALUES (201, '曼哈顿项目', "
+ QString::number(employeeId) + ")");
}
QSqlDatabase::database().commit();
如果数据库引擎支持事务处理,函数QSqlDriver::hasFeature(QSqlDriver::Transactions)将返回true。
您可以通过调用QSqlDatabase::transaction()来初始化事务。然后在该事务中执行您想要的工作。
完成后,执行QSqlDatabase::commit()提交事务或QSqlDatabase::rollback()取消事务。
这里有一个QSqlDriver::hasFeature(QSqlDriver::QuerySize)的例子,可以快速统计查询记录行数。
QSQLQUERYQUERY;
INTnumrows; Query.exec(“选择名称,来自员工的薪水,薪金> 50000”);
QSQLDABASEdefaultdb = qsqldatabase :: database()database() (defaultDB.driver()->hasFeature(QSqlDriver::QuerySize)) {
numRows = query.size();
} else {
// 这可能会很慢
query.last ();
numRows = www.sychzs.cn() + 1;
}
存储过程:
AsciiToInt() 是数据库中的存储过程。
但是我好像在网上看到说SQL Server中的存储过程是通过“EXEC”而不是“CALL”来完成的。我这里不太确定!留下问题~
QSqlQuery 查询;
query.prepare("CALL AsciiToInt(?, ?)");
query.bindValue(0, "A");
query.bindValue(1, 0, QSql ::Out);
query.exec();
int i = query.boundValue(1).toInt(); // 我是 65
■、使用SQL模型类
QSqlQueryModel:读取数据库数据的只读模型。
QSqlTableModel:无需编写SQL语句即可读写的单表模型。
QSqlRelationalTableModel:QSqlTableModel 的子类,可以将多个表关联在一起。
这些类都继承自 QAbstractTableModel,并且都继承自 QAbstractItemModel。
QSqlQueryModel 只读模式,基于SQL查询基础。
QSqlQueryModel 模型;
model.setQuery("SELECT * FROM 员工");
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 << 名称;
}
QSqlTableModel 可以对单个表进行读写操作。
//读取数据
QSqlTableModel model;
model.setTable("employee");
model.setFilter("salary > 50000");
model.setSort(2, Qt ::DescendingOrder);
www.sychzs.cn();
for (int i = 0; i < model.rowCount(); ++i) {
QString name = model.record(i). value("姓名").toString();
int 工资 = model.record(i).value("工资").toInt();
qDebug() << 姓名 << 工资;
}
//通过QSqlTableModel::setRecord()修改数据
for (int i = 0; i < model.rowCount(); ++i) {
QSqlRecord record = model.record(i );
双倍工资 = record.value("工资").toInt();
工资 *= 1.1;
record.setValue("工资", 工资);
model.setRecord( i, record);
}
model.submitAll();
//通过QSqlTableModel::setData()来更新一条记录
model.setData(model.index(row, column), 75000);
model.submitAll();
//插入一条记录
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();
//删除一条记录
model.removeRows(row, 5);
model.submitAll ();
函数 QSqlTableModel::submitAll() 确保记录写入数据库。
QSqlRelationalTableModel 通过外键实现多表关联。
//员工表与城市表和国家表关联。
model->setTable("员工");
model->setRelation(2, QSqlRelation("城市", "id", "姓名"));
model->setRelation(3, QSqlRelation (“国家”,“ID”,“名称”));
■,在数据呈现视图中
QSqlQueryModel、QSqlTableModel、QSqlRelationalTableModel一般都是借助QListView、QTableView、QTreeView来呈现~
这里不想详细解释QTableView了。这里我就不做过多介绍了。也许将来QTableView会被分离出来。 、QTableWidget详细介绍。
数据库部分是这次的重点!
继续讲解和补充QSqlRelationalTableModel,因为上面提到的太少了。
QSqlRelationalTableModel 模型;
model->setTable("员工");
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("www.sychzs.cn = '%1'").arg("Mucich"));
//model.setFilter(tr("employee.cityid = %1"). arg(312));
www.sychzs.cn();
//使用QTableView显示数据信息,
QTableView *view = new QTableView;
view->setModel(model);
//将表格中的项目设计为不可编辑模式
view->setEditTriggers(QAbstractItemView::NoEditTriggers);
view->show();
插入、更新、删除操作都是通过QSqlField进行的。继续上面的例子~
QSqlField idField("id", QVariant::Int);
QSqlField nameField("name", QVariant::String);
QSqlField cityIdField("cityId", QVariant::Int);
QSqlField CountryIdField("countryId", QVariant::Int);//一条记录Id = 12,名称= vic.MINg,城市=沉阳,国家/地区=中国。 (沉阳区号 024,中国 086)
idField.setValue(12);
nameField.setValue("vic.MINg");
cityIdField.setValue(24);
countryIdField.setValue( 86);//插入一条记录,-1表示在末尾添加
QSqlRecord记录;
record.append(idField);
record.append(nameField); cityIdField);
record.append(countryIdField);
模型->insertRecord(-1, 记录);//更新一条记录,row代表要修改的行
QSqlRecord record = model->record(row);
record.replace(1, nameField);
record.replace(2 , cityIdField);
record.replace(3,countryIdField);
model->setRecord(row, record);//删除一条记录,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();
//信号槽模型、视图、映射器三种机制连接在一起
connect(view-> SelectionModel(), SIGNAL(currentRowChanged(QModelIndex,QModelIndex)),
映射器, SLOT(setCurrentModelIndex(QModelIndex)));
http://www.sychzs.cn/blog/static/64339006200833024214394/
-->