Qt 之 QSqlQuery Class

详细描述

QSqlQuery 类提供了一种执行和操作SQL语句的方法。

QSqlQuery 封装了从在一个 QSqlDatabase(数据库连接)上的SQL 查询(queries) 创建,导航,检索(取回) 数据的功能。它可以用来执行DML(data manipulation language)即数据操作语句,比如 select,insert,update,delete 即数据库最常用的增删改查操作语句,也可以用来执行DDL(data definition language)即数据定义语句,例如 create table。它同样可以用来执行不属于国际标准SQL的特定数据库的命令(例如,PostgreSQL的 SET DATESTYLE=ISO)。


成功执行SQL语句会设置query的状态为活跃(active),isActive()  返回true。否则query的状态被设置为不活跃(inactive)。不论哪种情况,当执行一条新的SQL语句时,查询(query) 定位在一条无效的记录上。一个活跃的query查询在值可以被检索到之前必须被导航到一条有效的记录(因此isValid()返回true)。


对于一些数据库,当你调用 commit() 或者 rollback() 时如果一个活跃的查询(query)存在select语句,那么commit(事务)或者rollback(回滚)将会失败。


可以通过以下函数去访问查询到的数据库记录:next()previous()first()last()seek()。这些函数允许程序员向前,向后或者任意地访问query返回的记录。如果你只需要向前访问结果集(比如使用next()),你可以使用 setForwardOnly() ,这将节省大量的内存开销并提高某些数据库的性能。一旦一个活跃的查询被定位在一条有效的记录上,可以通过value()函数检索数据。所有数据都是使用QVariants数据类型从SQL 后台传输的。

举个例子:

   //查询之前记得先打开数据库连接。。。
   QSqlQuery query("SELECT country FROM artist");
    while (query.next()) {
        QString country = query.value(0).toString();
        doSomething(country);
    }

使用value(int)可以访问到query对象返回的数据。 由SELECT语句返回的数据中的每个字段都是通过在语句中传递字段的位置来访问的,从0开始。这使得使用SELECT *查询是不明智的,因为返回的字段的顺序是不确定的。

出于效率考虑,没有通过字段名访问字段内容的函数,除非你使用带名字的prepared queries(可是明明有QVariant QSqlQuery::value(const QString & name) const,。可能这个重载函数是在后面加入的,而当前的文档是还没加入这个重载函数的时候写的),使用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支持准备查询执行(prepared query execution)和将参数值绑定到占位符。一些数据库不支持这些特性,对于那些不支持的,Qt模拟了所需的功能。例如,Oracle和ODBC支持准备查询(prepared query),Qt使用支持的这种特性;但对于不支持这种特性的数据库,Qt自己实现了这些特性,比如说,当执行一条查询通过实际值去代替占位符。使用numRowsAffected() 找出多少条非查询(non-SELECT)查询生效,使用size()去找出由SELECT查找出的数量。


Oracle数据库通过 ‘冒号字段名’  来识别占位符,例如 :‘:name’.ODBC简单地使用了 ? 字符。这两种语法Qt都支持,限制条件是你不能在同一个查询中混合使用这两种语法。

你可以使用QMap QSqlQuery::boundValues() const检索在单个变量(映射 )中所有字段的值。例如:

    QMapIterator i(query.boundValues());
    while (i.hasNext()) {
        i.next();
        cout << i.key().toUtf8().data() << ": "
             << i.value().toString().toUtf8().data() << endl;
    }
等价于:

    QList list = query.boundValues().values();
    for (int i = 0; i < list.size(); ++i)
        cout << i << ": " << list.at(i).toString().toUtf8().data() << endl;

绑定值的几种方法

下面,我们将使用四种不同的绑定方法,每一种方法给出相同的示例,以及将值绑定到存储过程的一个示例。

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、使用位置占位符绑定值(版本1):
 
  
    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、使用位置占位符的绑定值(版本2):
 
  
 
  
 
  
    QSqlQuery query;
    query.prepare("INSERT INTO person (id, forename, surname) "
                  "VALUES (?, ?, ?)");
    query.addBindValue(1001);
    query.addBindValue("Bart");
    query.addBindValue("Simpson");
    query.exec();
 
  

将值绑定到存储过程(procedure):

这段代码调用了一个名叫AsciiToInt()的存储过程,通过参数传递一个字符,并将其结果输出到out参数中。

    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

 
  注意,未绑定的参数将保留它们的值。 
  

使用return语句返回值或返回多个结果集的存储过程没有得到完全的支持。具体细节请参见 SQL Database Drivers(可到Qt Assistant中检索关键字)。
警告:你必须在一个QSqlQuery创建之前加载SQL驱动和打开数据库连接(QSqlDatabase).并且,在QSqlQuery对象存在是数据库连接一定要保持打开;否则,QSqlQuery的行为是未定义的。

API介绍

bool QSqlQuery::execBatch(BatchExecutionMode mode = ValuesAsRows)
在批处理中执行提前准备好的SQL查询,所有的绑定参数都必须是QVariant的链表。如果数据库不支持批处理,则驱动程序将使用常规exec()调用来模拟它。查询成功执行返回true;否则返回false。
例子:
 
   
QSqlQuery q;
q.prepare("insert into myTable values (?, ?)");

QVariantList ints;
ints << 1 << 2 << 3 << 4;
q.addBindValue(ints);

QVariantList names;
names << "Harald" << "Boris" << "Trond" << QVariant(QVariant::String);
q.addBindValue(names);

if (!q.execBatch())
    qDebug() << q.lastError();

上面的例子在myTable表中插入了4个新行:
1  Harald
2  Boris
3  Trond
4  NULL

要绑定NULL值,必须将相关类型的空QVariant添加到绑定的QVariantList中;比如,如果你使用strings(字符串)QVariant(QVariant::String)应该被添加到QVariantList中。
注意:每个绑定的QVariantList必须包含相同数量的变体。
注意:列表中的QVariant的类型不能改变。例如,您不能在QVariantList中混合整数和字符串变体。


 
  
 
  
 
 

你可能感兴趣的:(Qt,SQL,数据库)