QACI编程概述

QACI依赖的动态库

QQt的应用程序在加载qsqlaci动态库的时候需要同时加载aci。这里有两种方法让aci正确加载:

  1. 隐式加载。Windows_64环境下把aci.dll放到Path环境变量下;Linux_64环境下把libaci.so放到LD_LIBRARY_PATH下。
  2. 显示加载。如果Path环境变量或者LD_LIBRARY_PATH下没有aci,可以在应用程序加载qsqlaci动态库的代码前用函数显示加载,见应用举例。显示加载的好处在于如果QACI没有正确加载,可以先检查aci是否正确加载,排除QACI没有正确加载的部分原因。

QACI的存放路径

Qt指定了数据库驱动动态库路径。路径为:Qt开发环境/plugins/sqldrivers

以Qt5.5.1为例:

Windows_64环境:c:QTQt5.5.15.5msvc2013_64pluginssqldrivers

Linux_64环境: /opt/Qt5.5.1/5.5/gcc_64/plugins/sqldrivers

QACI的数据结构

当使用QACI接口来连接神通数据库的时候,常用的类有以下几种:

类名 引用的头文件 解释
QSqlDatabase #include <QSqlDatabase> 表示一个数据库连接
QSqlQuery #include <QSqlQuery> 提供对sql语句的操作和执行
QSqlRecord #include <QSqlRecord> 封装一个数据库记录
QSqlDriver #include <QSqlDriver> 连接特定数据库的抽象基类
QSqlIndex #include <QSqlIndex> 提供函数操作和解释数据库索引

QACI事务

QACI的事务默认为自动提交,即执行了QSqlQuery::exec方法后,事务会被自动提交,如果想显示开启事务并手动提交,需要知识QSqlDatabase::database().transaction()和QSqlDatabase::database().commit()、QSqlDatabase::database().rollback()方法。

QACI支持数据类型

序号 数据库类型 QT类型 C类型 备注
1 Smallint QVariant::Int Short int  
2 Int QVariant::Int Int  
3 Bigint QVariant::Longlong Long long  
4 Double precision QVariant::Double double  
5 Decimal/Number(p,s) QVariant::Double double  
6 Float/Float(n) QVariant::Double double  
7 Char(n) QVariant:: QString Char *  
8 varchar(n)/ varchar2(n) QVariant:: QString Char *  
9 binary QVariant::QByteArray Char *  
10 varbinary QVariant::QByteArray Char *  
11 Time(p) QVariant::Time ————  
12 date QVariant::Date ————  
13 Timestamp(p) QVariant::DateTime ———— 数据库精度p>=6,但QT只支持3为小数
14 Interval day to second QVariant:: QString Char * 数据库默认date只有年月日,如果是Oracle兼容模式并设置了DATEFORMAT属性,可包含时分秒,不支持毫秒
15 Interval year to month QVariant:: QString Char * 数据库精度p>=6,但QT只支持3为小数
16 BLOB QVariant::QByteArray Char * Interval类型QT无对于类型,可通过字符串方式读写
17 CLOB QVariant:: QString Char * 数据库支持4GB,QByteArray/ QString支持的大小由内存决定,但时间情况存储文件较大时,QT处理效率比较低。

QACI数据转换

../../../../_images/image517.png

QACI对数据库操作的支持情况

不支持的操作

  • 不支持一次执行多次sql

因为QACI是底层为aci接口,aci为仿Oracle的OCI接口,而OCI接口是不支持多条sql同时执行的,aci为了保持一致性,也不支持,因此QACI也是不支持的。 比如:

query.exec(insert into test values(1, 'aaa'); insert into test values(2, 'bbb');") ;不支持

在特殊场景中,如果想一次执行多个sql(非返回结果集的SQL),可用匿名块实现,比如:

query.exec(begin insert into test values(1, 'aaa'); insert into test values(2, 'bbb');  end;") ;
  • 不支持lastInsertId操作

QSqlQuery类有个lastInsertId方法,由于返回最后插入数据的RowId,目前不支持,处理办法为可以通过数据库的returing语法实现,比如:

QSqlQuery query;
query.prepare("insert into test values(?,?) returning a into ? ");
query.bindValue(0,999);
query.bindValue(1,"移植3");
query.bindValue(2,0,QSql::Out);
query.exec();
qDebug()<<query.boundValue(2).toInt();
db.commit();
  • 二进制数据类型的返回

目前因为神通的aci接口中的ACIStmtGetPieceInfo和ACIStmtSetPieceInfo接口存在问题,导致QACI无法获得binary和varbianry类型的数据,后续支持。

  • Refcursor类型无法操作

QT原生自带的QOCI也无法操作Oracle的sys_refcursor游标,后续可考虑支持。

/*
create or replace procedure prefcursor(id int ,tname out varchar(30),rescur out sys_refcursor)
as
begin
  tname = 'test';
open rescur for select *from test;
end;
/

对于prefcursor存储过程,rescur为out的游标参数,目前是没有办法获得的。

额外支持的操作

以下罗列QACI相对于QOCI接口增加的功能

  • 支持Bool类型

神通数据库中有bool数据库类型,QOCI不支持,通过修改可以支持,获取方式如下:

//create table tbbool( a int,b bool);
QSqlQuery query;
query.exec("truncate table tbbool");
query.prepare("insert into tbbool values(?,?)");
query.bindValue(0,13);
query.bindValue(1,true);
query.bindValue(0,15);
query.bindValue(1,false);
query.exec();
  • 支持time、date、timestamp类型

原生QOCI只支持QDateTime类型,且不支持对于time类型和timestamp类型的毫秒精度,通过修改,可支持这三种类型,同时毫秒精度可支持3为小数(因为QDateTime的格式化字符串中,毫秒值精确到了3位):

//create table tbtime( a int,b date,c time,d timestamp(6));
QSqlQuery query;
query.exec("drop table tbtime");
query.exec("create table tbtime( a int,b date,c time,d timestamp(6))");

query.prepare("insert into tbtime values(?,?,?,?)");
QDate c11 = QDate::currentDate();
QTime c21 = QTime::currentTime();
QDateTime c31 = QDateTime::currentDateTime();

query.bindValue(0,11);
query.bindValue(1,c11);
query.bindValue(2,c21);
query.bindValue(3,c31);
query.exec();