Win10 Qt5.12 oracle11g 64位下编译oci驱动 Qt5.12远程连接Oracle数据库

在win10下通过Qt5.12编译Oracle数据库驱动时,打开X:\Qt\Qt5.12.0\5.12.0\Src\qtbase\src\plugins\sqldrivers\oci下的工程文件,在oci.pro文件中更改如下所示:

TARGET = qsqloci

HEADERS += $$PWD/qsql_oci_p.h
SOURCES += $$PWD/qsql_oci.cpp $$PWD/main.cpp

#QMAKE_USE += oci
QMAKE_LFLAGS += oci.lib

darwin:QMAKE_LFLAGS += -Wl,-flat_namespace,-U,_environ

OTHER_FILES += oci.json

PLUGIN_CLASS_NAME = QOCIDriverPlugin
include(../qsqldriverbase.pri)
INCLUDEPATH += E:\OCI\include
LIBPATH += E:\OCI\lib\MSVC

需要把Oracle安装包下的OCI目录里面的include和lib的目录添加进来,如果你的电脑没有安装Oracle,那就去已经安装Oracle的电脑上对应的目录拷贝一份即可,然后按照上述代码进行配置即可;

在编译后很可能遇到下述bug:error: use of undeclared identifier 'OCIBindByPos2'

error: use of undeclared identifier 'OCIBindByPos2'

这是因为在Qt5.12里面调用的是OCIBindByPos2()函数,这个函数的第九个参数的数据类型是ub4*,但是根据oracle官方的说法:在这里找到的思路:是新的OCIBindByPos2()函数和以前的OCIBindByPos()函数有一定的区别,为了能在最新的Qt5.12上能成功编译Oracle驱动,我们需要对oci项目下的qsql_oci.cpp的1559行代码附近进行修改如下:

  // binding the column
        r = OCIBindByPos(
                d->sql, &bindColumn.bindh, d->err, i + 1,
                bindColumn.data,
                bindColumn.maxLen,
                bindColumn.bindAs,
                bindColumn.indicators,
                reinterpret_cast<ub2*>(bindColumn.lengths),
                0,
                arrayBind ? bindColumn.maxarr_len : 0,
                arrayBind ? &bindColumn.curelep : 0,
                OCI_DEFAULT);

这么做是将OCIBindByPos2()函数替换成OCIBindByPos()但是OCIBindByPos()函数的第九个参数是ub2*,但是实际上

bindColumn.length实际上是ub4*,因此需要一个强制转换,转换完毕之后,qmake,然后重新生成项目即可,这样就完全解决这个问题了。

 

重新生成之后就可以在X:\plugins\sqldrivers目录下找到所需要的qsqloci.dll和qsqlocid.dll,这就生成了我们所需要的驱动。然后将驱动放在E:\Qt\Qt5.12.0\5.12.0\msvc2017_64\plugins\sqldrivers目录下,你用那个编译器,就放在那个目录下。比如我用的是msvc2017_64.

 

将驱动文件放好之后,新建一个工程,测试一下oracle数据库连接:

 //连接oracle数据库
    QSqlDatabase db = QSqlDatabase::addDatabase("QOCI");
    db.setPort(1521);
    db.setHostName("name");
    db.setDatabaseName("ORCL");
    db.setUserName("uname");
    db.setPassword("pwd");
    if (!db.open()) {
        qDebug()<< db.lastError().text();
    }else{
        qDebug()<< u8"链接远程数据库成功";
    }

到了这一步,可能会出现两种报错如下:

empty inner name and ver.

Dynamic-----------------screen need SpecialCtrl mon 1

QSqlDatabase: QOCI driver not loaded

QSqlDatabase: available drivers: QSQLITE QMYSQL QMYSQL3 QOCI QOCI8 QODBC QODBC3 QPSQL QPSQL7

"Driver not loaded Driver not loaded"

 

第二个报错:

inner:

empty inner name and ver.

Dynamic-----------------screen need SpecialCtrl mon 1

QOCIDriver: unable to create environment

" Unable to logon"

出现这两种报错,是因为没有相对于的Oracle库,需要在已经安装Oracle客户端的电脑拷贝两个库文件:oci.dll和oraociei11.dll,将这两个库放到你工程生成的exe目录下,然后重新运行Qt项目。即可成功连接数据库。

oci函数的详细介绍 和应用实例 OCI 连接过程比较复杂,除了分配设置各个基本句柄外,还要明确彼此之间的联系,大致流程如下: 创建环境句柄: OCIEnvCreate(&envhp;, …); 创建一个指定环境的错误句柄: OCIHandleAlloc((dvoid *)envhp, (dvoid **)&errhp;,…); 创建一个指定环境的服务器句柄: OCIHandleAlloc((dvoid *)envhp, (dvoid **)&servhp;,…); 建立到数据源的访问路径 : OCIServerAttach(servhpp, errhpp,…); 创建一个指定环境的服务上下文句柄: (void) OCIHandleAlloc((dvoid *)envhpp,…); 为指定的句柄及描述符设置特定的属性: (void) OCIAttrSet((dvoid *)svchpp,…); 创建一个指定环境的用户连接句柄: (void) OCIHandleAlloc((dvoid *)envhpp,…); 为用户连接句柄设置登录名及密码: (void) OCIAttrSet((dvoid *)usrhpp,…); 认证用户建立一个会话连接OCISessionBegin(svchpp, errhpp,…); 创建一个句子句柄: OCIHandleAlloc((dvoid *)envhpp,…);s 准备 SQL 语句: OCIStmtPrepare(stmthpp, errhpp,…); 绑定输入变量: OCIBindByPos(stmtp &hBind;, errhp,…); 绑定输出变量: OCIDefineByPos(stmthpp, &bhp1;, errhpp,…); 获得 SQL 语句类型: OCIAttrGet ((dvoid *)stmthpp, (ub4)OCI_HTYPE_STMT,…); 执行 SQL 语句: OCIStmtExecute(svchpp, stmthpp,…); 释放一个会话: OCISessionEnd(); 删除到数据源的访问 : OCIServerDetach(servhpp, errhpp, OCI_DEFAULT); 释放句柄: OCIHandleFree((dvoid *) stmthpp, OCI_HTYPE_STMT);
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值