2.Books
Books示例说明了Qt中SQL类如何被Model/View框架使用,使用数据库中存储的信息,创建丰富的用户界面。
首先介绍使用SQL我们需要了解的类:
1.QSqlDatabase:
QSqlDatabase类表示与数据库的连接。
QSqlDatabase类提供了一个通过连接访问数据库的接口。 QSqlDatabase的一个实例表示连接。连接通过驱动(驱动就是QSqlDriver派生类)访问数据库。或者,你自己子类化QSqlDriver,编写自己的数据库驱动。
通过调用静态addDatabase()函数创建一个连接。addDatabase()函数需要2个参数,第一个指定的驱动,第二个连接名称。Qt支持的驱动如下:
驱动 | 数据库 |
---|---|
QDB2 | IBM DB2 (7.1 或更新版本) |
QIBASE | Borland InterBase |
QMYSQL | MySQL |
QOCI | Oracle Call Interface Driver |
QODBC | Open Database Connectivity (ODBC) – Microsoft SQL Server 及其它兼容 ODBC 的数据库 |
QPSQL | PostgreSQL (7.3 或更新版本) |
QSQLITE2 | SQLite 2 |
QSQLITE | SQLite 3 |
QSYMSQL | 针对 Symbian 平台的SQLite 3 |
QTDS | Sybase Adaptive Server (自 Qt 4.7 起废除) |
连接通过设定的连接名称区分,可以多个连接连接到同一个数据库。 QSqlDatabase还支持默认连接的概念,连接未命名就是默认连接。 要创建默认连接,调用addDatabase()时不要传递连接名参数。随后,当您调用任何使用连接名称参数的静态成员函数时,如果不传递连接名称参数,则假定为默认连接。以下代码段显示了如何创建和打开与PostgreSQL数据库的默认连接:
QSqlDatabase db = QSqlDatabase::addDatabase("QPSQL");
db.setHostName("acidalia");
db.setDatabaseName("customdb");
db.setUserName("mojito");
db.setPassword("J0a1m8");
bool ok = db.open();
创建QSqlDatabase对象后,使用setDatabaseName(),setUserName(),setPassword(),setHostName(),setPort()和setConnectOptions())设置连接参数。连接初始状态是不可用的,直到你调用open()函数激活与数据库的物理连接。
上面定义的连接将是默认连接,因为我们没有给addDatabase()提供连接名称。 随后,您可以通过调用没有连接名称参数的database()来获取默认连接:
QSqlDatabase db = QSqlDatabase::database();
QSqlDatabase是一个value class。通过QSqlDatabase实例改变一个连接,会影响其他代表同一个连接的实例。所以使用cloneDatabase()函数创建一个独立的连接,修改这个独立连接而不影响其他连接。
如果你创建多个数据库连接,请在调用addDatabase()时为每个连接指定唯一的连接名称。使用具有连接名称的database()来获取该连接。使用带有连接名称的removeDatabase()来删除连接。如果您尝试删除由其他QSqlDatabase对象引用的连接,QSqlDatabase将输出警告。 使用contains()来查看给定的连接名称是否在连接列表中。
一旦建立连接,您可以调用tables()获取数据库中的表的列表,调用primaryIndex()获取表的主索引,并调用record()获取有关表的字段的元信息。
注意:不推荐使用QSqlDatabase :: exec()。 推荐用QSqlQuery :: exec()。
如果驱动程序支持事务,请使用transaction()来启动一个事务,commit()或rollback()来完成它。使用hasFeature()来询问驱动程序是否支持事务。注意:使用事务时,必须先创建事务,然后再创建查询。
如果发生错误,lastError()将返回有关它的信息。
使用drivers()获取可用的SQL驱动程序的名称。 使用isDriverAvailable()检查特定驱动程序的存在。 如果您创建了自己的自定义驱动程序,则必须使用registerSqlDriver()注册它。
2.QSqlQuery
QSqlQuery类提供了一种执行和操作SQL语句的方法。
QSqlQuery封装了在QSqlDatabase中执行的SQL操作。它可以用于执行DML(数据操作语言)语句,如SELECT,INSERT,UPDATE和DELETE以及DDL(数据定义语言)语句,如CREATE TABLE。 它也可以用于执行不是标准SQL的数据库特定的命令(例如PostgreSQL数据库 SET DATESTYLE = ISO)。
成功执行SQL语句将query的状态设置为active,以使isActive()返回true。否则query的状态设置为inactive。在任一情况下,执行新的SQL语句时,query位于无效记录上。 必须将active query导航到有效的记录(isValid()返回true)才能检索到值。
对于某些数据库,当active query是SELECT语句时,当你调用commit()和rollback()函数处理事务时,会失败。当active query是SELECT语句时,必须调用finish()和clear()函数,使得query变成incative,再调用事务。
使用以下函数执行导航记录:
next()
previous()
first()
last()
seek()
这些函数允许程序员向前,向后或任意地移动query返回的记录。如果您仅需要前进的结果(例如,使用next()),则可以使用setForwardOnly(),这将节省大量内存开销并提高某些数据库的性能。一旦active query位于有效的记录上,可以使用value()检索数据。 所有从SQL端传送过来的数据都是QVariant类型。
举例:
QSqlQuery query("SELECT country FROM artist");
while (query.next()) {
QString country = query.value().toString();
doSomething(country);
}
要获得查询返回的数据,请使用value(int)。字段从0开始,比如"SELECT country FROM artist"只有一个字段。我们使用query.value(0)就可以获得QVariant类型的值。"SELECT forename, surname FROM people;" 此时forename字段0,surname 字段1.我们要获得surname的值query.value(1).toString()。所以使用select *是不建议的,因为你无法确定字段的顺序。
如果我们硬是要使用select *怎么办?先调用record()函数获得整个查询的记录,然后调用indexOf()函数,从记录中查找字段的位置。
QSqlQuery query("SELECT * FROM artist");
int fieldNo = query.record().indexOf("country");
while (query.next()) {
QString country = query.value(fieldNo).toString();
doSomething(country);
}
QSqlQuery支持预查询执行和占位符参数绑定。某些数据库不支持这些功能,因此对于这些数据库,Qt会模拟所需的功能。例如,Oracle和ODBC驱动程序具有预查询支持,Qt利用它; 但是对于不支持这种操作的数据库,Qt自身实现了这个特征。例如:在查询操作时,用占位符替换实际的值,使用numRowsAffected()函数获得非SELECT查询影响的行数。使用size()函数获得SELECT语句查询的行数。
Oracle数据库通过使用冒号语法来标识占位符,例如 :name。 ODBC只是使用?字符来标识占位符。Qt两种语法都支持,但是限制是不能混合使用。
您可以通过boundValues()函数由一个变量(QMap<QString, QVariant>)获得所有字段的值。
下面我们将介绍4中不同的占位符参数绑定方法和1中绑定值到存储过程的示例:
1.通过字段的名称绑定。
QSqlQuery query;
query.prepare("INSERT INTO person (id, forename, surname) "
"VALUES (:id, :forename, :surname)");
query.bindValue(":id", );
query.bindValue(":forename", "Bart");
query.bindValue(":surname", "Simpson");
query.exec();
2.通过字段的位置绑定
QSqlQuery query;
query.prepare("INSERT INTO person (id, forename, surname) "
"VALUES (:id, :forename, :surname)");
query.bindValue(, );
query.bindValue(, "Bart");
query.bindValue(, "Simpson");
query.exec();
3.通过字段位置绑定,占位符由 :something 换成 ?
QSqlQuery query;
query.prepare("INSERT INTO person (id, forename, surname) "
"VALUES (?, ?, ?)");
query.bindValue(, );
query.bindValue(, "Bart");
query.bindValue(, "Simpson");
query.exec();
4.通过字段位置绑定, addBindValue()函数和查query语句中占位符的位置一致。
QSqlQuery query;
query.prepare("INSERT INTO person (id, forename, surname) "
"VALUES (?, ?, ?)");
query.addBindValue();
query.addBindValue("Bart");
query.addBindValue("Simpson");
query.exec();
绑定值到存储过程。
下面的代码调用一个叫做AsciiToInt()的存储过程。第一个参数字符,第二个参数存储过程的返回值。
QSqlQuery query;
query.prepare("CALL AsciiToInt(?, ?)");
query.bindValue(, "A");
query.bindValue(, , QSql::Out);
query.exec();
int i = query.boundValue().toInt(); // i is 65
QSql::Out 表示绑定值从数据库获得数据。
请注意,未绑定的参数将返回其本身的值。
存储过程使用return语句返回值或者返回多个结果集,Qt并不是完全支持。
注意:在创建QSqlQuery之前,必须加载SQL驱动程序并打开连接。 另外,执行query操作时,连接必须保持打开; 否则,QSqlQuery的行为是未定义的。
3.QSqlError
QSqlError类提供SQL数据库错误信息。
QSqlError对象可以提供数据库明确的错误信息。driverText()返回数据库驱动得到的错误信息,databaseText()返回数据库得到的错误消息(两者合并就是text()),number()返回错误数量,type()返回错误类型。 这些函数都具有设置器,以便您可以从自己的类创建和返回QSqlError对象,例如从你自定义SQL驱动程序。
2.Books的更多相关文章
- 7 Must Read Python Books
7 Must Read Python Books I started learning Python just two years ago. Coming from a C++ and Java ba ...
- TCP/IP BOOKS
TCP/IP Fundamentals for Microsoft Windows: Overview https://technet.microsoft.com/en-us/library/bb72 ...
- UVa 714 Copying Books(二分)
题目链接: 传送门 Copying Books Time Limit: 3000MS Memory Limit: 32768 KB Description Before the inventi ...
- LightOJ1283 Shelving Books(DP)
题目 Source http://www.lightoj.com/volume_showproblem.php?problem=1283 Description You are a librarian ...
- 抄书 Copying Books UVa 714
Copying Books 题目链接:http://acm.hust.edu.cn/vjudge/contest/view.action?cid=85904#problem/B 题目: Descri ...
- [LintCode] Copy Books 复印书籍
Given an array A of integer with size of n( means n books and number of pages of each book) and k pe ...
- JSTL标签出错:<c:forEach var="book" items="${requestScope.books}" varStatus="status">
今天在运行书里的JSTL标签代码的时候出错,总结一下: 问题1.The JSP specification requires that an attribute name is preceded by ...
- A Year Of Books - 2016 Javaer书单
A Year Of Books - 2016 Javaer书单 (PS:欢迎留言推荐,很多来自白衣大哥的推荐) 1. OS & Networking <编码 : 隐匿在计算机软硬件背后的 ...
- A Personal Selection of Books on E lectromagnetics and Computational E lectromagnetics---David B. Davidson
链接. General Books on Electromagnetics When our department recently reviewed our junior-level text, w ...
- 【NOIP提高组2015D2T1】uva 714 copying books【二分答案】——yhx
Before the invention of book-printing, it was very hard to make a copy of a book. All the contents h ...
随机推荐
- Angular2常用命令
一.常用命令 1.1 npm config list配置项目 可进行相关代理配置,通常可以配置在网络环境较差的情况下,配置相关代理.相关的设置命令如图: 1.2 ng 新建启动项目 ng new pr ...
- 手把手使用 Webpack 4 建立 VUE 项目
手把手使用 Webpack 4 建立 VUE 项目 安装 node.js 略 安装 cnpm 略 安装 webpack cnpm install webpack -g 安装 vue-cli cnpm ...
- lbypmall系统备份恢复
打开phpmyadmin 1.数据库创建,在服务器上创建lbypmall数据库,排序规则utf8_general_ci 2.mysqldump -u root -p lbypmall > lby ...
- maven命令行创建web项目报错:java.lang.NoClassDefFoundError: org/apache/commons/lang/StringUtils
早上一上班就想新建一个web项目玩玩,没想到一敲命令创建就失败了,真是出师不利.各种折腾无果,当然我也可以用eclipse直接创建的,就是不甘心被这破问题给耍了.刚刚才发现问题原因,这个结果我也是醉了 ...
- 有限状态机(Finite-state machine, FSM)的C语言实现
有限状态机,也称为FSM(Finite State Machine),其在任意时刻都处于有限状态集合中的某一状态.当其获得一个输入字符时,将从当前状态转换到另一个状态,或者仍然保持在当前状态.任何一个 ...
- Goclipse on Eclipse
Goclipse插件安装地址 https://goclipse.github.io/releases gocode.godef都可以通过Download快速安装 但guru容易失败:package g ...
- Oracle10g客户端连接远程数据库配置图解
yuanwen:http://blog.csdn.net/DKZhu/article/details/6027933 一. 安装oracle客户端 1. 运行setup.exe,出现 2. ...
- [Android]异步任务AsyncTask使用解析
AsyncTask主要用来更新UI线程,比较耗时的操作可以在AsyncTask中使用. AsyncTask是个抽象类,使用时需要继承这个类,然后调用execute()方法.注意继承时需要设定三个泛型P ...
- yield-from示例
#!/usr/bin/python3# -*- coding: utf-8 -*-# @Time : 2018/6/20 9:13# @File : yield_from11.py fro ...
- Py修行路 python基础 (五)三元运算 字符编码 元组 集合 三级菜单优化!
三元运算 条件判断不能加冒号: a=3 b=5 c=a if a<b else b oct() 转成八进制的简写:16进制 标志:BH为后缀或是0x为前缀hex() 转成16进制 元组 跟列表是 ...