• 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(0).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", 1001);
         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(0, 1001);
         query.bindValue(1, "Bart");
         query.bindValue(2, "Simpson");
         query.exec(); 

    3.通过字段位置绑定,占位符由 :something 换成 ?

         QSqlQuery query;
         query.prepare("INSERT INTO person (id, forename, surname) "
                       "VALUES (?, ?, ?)");
         query.bindValue(0, 1001);
         query.bindValue(1, "Bart");
         query.bindValue(2, "Simpson");
         query.exec();

    4.通过字段位置绑定, addBindValue()函数和查query语句中占位符的位置一致。

         QSqlQuery query;
         query.prepare("INSERT INTO person (id, forename, surname) "
                       "VALUES (?, ?, ?)");
         query.addBindValue(1001);
         query.addBindValue("Bart");
         query.addBindValue("Simpson");
         query.exec();

    绑定值到存储过程。

    下面的代码调用一个叫做AsciiToInt()的存储过程。第一个参数字符,第二个参数存储过程的返回值。

         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

    QSql::Out 表示绑定值从数据库获得数据。

    请注意,未绑定的参数将返回其本身的值。

    存储过程使用return语句返回值或者返回多个结果集,Qt并不是完全支持。

    注意:在创建QSqlQuery之前,必须加载SQL驱动程序并打开连接。 另外,执行query操作时,连接必须保持打开; 否则,QSqlQuery的行为是未定义的。

    3.QSqlError

    QSqlError类提供SQL数据库错误信息。

    QSqlError对象可以提供数据库明确的错误信息。driverText()返回数据库驱动得到的错误信息,databaseText()返回数据库得到的错误消息(两者合并就是text()),number()返回错误数量,type()返回错误类型。 这些函数都具有设置器,以便您可以从自己的类创建和返回QSqlError对象,例如从你自定义SQL驱动程序。

    
    
    
  • 相关阅读:
    idea spring boot启动项目上面有红色叉
    hibernate Criteria中多个or和and的用法 and ( or or)
    CAS Server 4.2.7(自定义密码验证) 部署
    Web应用系统集成CAS-rest指南
    用DBMS_REDEFINITION将普通表转换为分区表
    windows编译libevent时报告“缺少print_winsock_errors.obj”的解决
    Oracle表增删分区的脚本
    libcassandra开发示例
    关于MongoDB API的两个小经验
    C/C++开发Cassandra的一些经验
  • 原文地址:https://www.cnblogs.com/billxyd/p/6997014.html
Copyright © 2020-2023  润新知