数据库操作
来源:互联网 发布:军火女王 知乎 编辑:程序博客网 时间:2024/05/21 10:37
- 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)));
0 0
- 操作数据库
- 数据库操作
- 数据库操作
- 数据库操作
- 数据库操作
- 数据库操作
- 数据库操作
- 数据库操作
- 数据库操作
- 数据库操作
- 数据库操作
- 数据库操作
- 数据库操作
- 数据库操作
- 数据库操作
- 数据库操作
- 操作数据库
- 数据库操作
- SQL SERVER 创建计算列
- sql 语句中 可为null列的判断要小心
- 良好的工作习惯和团队管理方法(想到一点写一点)
- 消息队列函数(msgget、msgctl、msgsnd、msgrcv)
- STL源码分析--萃取编程(traits)技术的实现
- 数据库操作
- Single number系列
- bcb中TChart组件的简单应用
- Integer与int的种种比较你知道多少?
- Jpa另一种分页取数据
- [Qt] 配置VS2010下Qt项目的环境 (附:如何配置外部库)
- 正则表达式
- Java反射机制的一些问题
- 嵌入式裸机开发学习:中断标志的清除顺序SUBSRCPND-->SRCPND-->INTPND