当前位置:科技动态 > Qt数据库操作(qt-win-commercial-src-4.3.1、VC6、Oracle、SQL Server)

Qt数据库操作(qt-win-commercial-src-4.3.1、VC6、Oracle、SQL Server)

  • 发布:2023-10-05 07:44

-->

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())
    {
        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;
}

? , " ODBC" );
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[])
{
  QApplication app(argc, argv);
  QTextCodec::setCodecForCStrings(QTextCodec::codecForLocale());
  QTextCodec ::setCodecForTr(QTextCodec::codecForLocale());
QFont 字体("Times", 9, QFont::Normal, FALSE);
app.setFont(font);

? ? SqlDatabase::database( "ORACLE" );
// 现在我们可以在 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::Horizo​​ntal, QObject:: tr("ID"));
model->setHeaderData(1, Qt::Horizo​​ntal, QObject::tr("Name"));
model->setHeaderData(2, Qt::Horizo​​ntal, QObject ::tr("City"));
model->setHeaderData(3, Qt::Horizo​​ntal, 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/

-->

相关文章