Orcale中OCILogon和OCIServerAttach登录方式的区别分析

参考文档《Oracle Call Interface Programmer's Guide》

        在Orcale和DM数据库提供的API中,通过OCI方式接口连接数据库的方法有多个,这里只讨论OCILogon和OCIServerAttach的比较。

1、官方描述

根据文档里的描述:

OCILogon():This function is used to create a simple logon session for an application.

OCILogon()适用于应用程序对于某一数据库连接仅支持单用户进程。

OCI内部过程的调用顺序基本如下:
 OCIEnvCreate
 OCIHandleAlloc  <ERROR>
 OCILogon
 OCILogoff
 OCIHandleFree   <ERROR>
 OCIHandleFree   <ENV>

OCIServerAttach():This call is used to create an association between an OCI application and a particular server

OCIServerAttach()适用于应用程序对单一数据库连接需要维护多个用户会话

每个句柄在这里都是手工去创建。所有的OCI句柄都有其相关属性,这些属性存储了一些有用的数据。可以使用OCIAttrGet()获取对应信息,也可以通过OCIAttrSet()进行修改。OCIServerAttach() 创建了一个OCI操作的数据服务访问路径,OCISessionBegin() 确立用户会话连接。这里完成后,才可以进行实际的数据操作。注意这里的OCIAttrSet()和OCIServerAttach()的调用顺序不是固定的,类似的 OCISessionBegin() 和 OCIAttrSet() 先后顺序也是可以互换的。

2、结论

单个用户,单个连接

单个用户单个连接这种是最简单的登录方式,可以在应用对每个数据库连接仅维护一个用户会话的情况下使用

当应用调用OCILogon2()或OCILogon()时,OCI库对传递给它的服务上下文句柄进行初始化,为发请求的用户创建到指定Oracle数据库的连接。

非代理的多会话或多连接

非代理多会话或连接方式,通过显式地添加和调用启用会话函数来维护一个数据库连接上的多个用户会话和连接。 附加到 Oracle 数据库和开始会话的特定函数有:

OCIServerAttach()——为OCI操作创建到Oracle数据库地访问路径

OCISessionBegin()——为用户创建到特定Oracle数据库的会话。这个函数对于需要在Oracle数据库上执行操作的用户来说是必须的。

再次调用OCISessionBegin()时使用不同的服务上下文句柄和会话上下文句柄会导致前一个用户登出,并引发错误。要想同时运行两个不可互相替代的会话,第二次调用OCISessionBegin()函数时必须指定一个相同的服务上下文句柄和一个新的会话上下文句柄。

3、拓展介绍-句柄

3.1 定义

几乎每个OCI调用的参数列表中都会包含一个或多个句柄。一个句柄就是一个指向由OCI库分配的存储空间的不透明指针。应用可以使用句柄存储上下文或连接信息,例如环境或服务上下文句柄,也可以存储OCI函数或数据的信息,例如错误或describe句柄。句柄让编程变得简单,因为是使用库来维护数据而非应用来维护数据。
大多数OCI应用必须要获取存储在句柄中的信息,所以设计通过set和get属性的OCI调用,OCIAttrGet()和OCIAttrSet()来访问或设置这些信息。

3.2 句柄类型

        下表列出了OCI中的各类句柄,每种句柄类型对应的C数据类型以及在OCI调用中标识句柄类型的常量表示

描述

C数据类型

类型常量

OCI环境句柄

OCIEnv

OCI_HTYPE_ENV

OCI错误句柄

OCIError

OCI_HTYPE_ERROR

OCI服务和上下文句柄

OCISvcCtx

OCI_HTYPE_SVCCTX

OCI语句句柄

OCIStmt

OCI_HTYPE_STMT

OCI绑定句柄

OCIBind

OCI_HTYPE_BIND

OCI定义句柄

OCIDefine

OCI_HTYPE_DEFINE

OCI描述句柄

OCIDescribe

OCI_HTYPE_DESCRIBE

OCI服务器句柄

OCIServer

OCI_HTYPE_SERVER

OCI用户会话句柄

OCISesseion

OCI_HTYPE_SESSION

OCI验证信息句柄

OCIAuthInfo

OCI_HTYPE_AUTHINFO

OCI连接池句柄

OCICPool

OCI_HTYPE_CPOOL

OCI会话池句柄

OCISPool

OCI_HTYPE_SPOOL

OCI事务句柄

OCITrans

OCI_HTYPE_TRANS

OCI复杂对象检索(COR)句柄

OCIComplexObject

OCI_HTYPE_COMPLEXOBJECT

OCI线程句柄

OCIThreadHandle

不适用

OCI订阅句柄

OCISubscription

OCI_HTYPE_SUBSCRIPTION

OCI直接路径上下文句柄

OCIDirPathCtx

OCI_HTYPE_DIRPATH_CTX

OCI直接路径函数上下文句柄

OCIDirPathFuncCtx

OCI_HTYPE_DIRPATH_FN_CTX

OCI直接路径列数组句柄

OCIDirPathColArray

OCI_HTYPE_DIRPATH_COLUMN_ARRAY

OCI直接路径流句柄

OCIDirPathStream

OCI_HTYPE_DIRPATH_STREAM

OCI进程句柄

OCIProcess

OCI_HTYPE_PROC

OCI管理句柄

OCIAdmin

OCI_HTYPE_ADMIN

OCI HA 事件句柄

OCIEvent

不适用

3.3 分配和释放句柄

除了绑定、定义、线程句柄之外,其他句柄的分配都是针对一个特定环境句柄来说的。在执行分配句柄的调用时,需要将环境句柄作为参数之一传入,因此分配的句柄是特定于一个环境的。

绑定和定义句柄是特定于语句句柄分配的,其中包含语句句柄所代表的语句的一些信息。

绑定和定义局部由OCI库隐式地分配,不需要用户分配。

环境句柄由OCIEnvCreate()或OCIEnvNlsCreate()的调用完成分配和初始化。任何一个OCI应用都需要用到这两个函数中的一个。

所有用户分配的句柄的初始化都通过调用OCI句柄分配函数OCIHandleAlloc()来完成。

句柄的类型包括:会话池句柄,直接路径上下文句柄,线程句柄,COR句柄,订阅句柄,描述句柄,语句句柄,服务上下文句柄,错误句柄,服务器句柄,连接池句柄,HA事件句柄,管理句柄。

线程句柄通过OCIThreadHndInit()调用进行分配。

所有应用必须释放不再使用的句柄,释放句柄的通过OCIHandleFree()完成。

注意:

当一个母句柄释放,所有与其关联的子句柄都将一并释放并且不能再被使用。例如一个语句句柄被释放后,任何与其相关的绑定句柄和定义句柄都会一并释放。

句柄减少了对全局变量的需求,同时简化了错误报告,可以使用一个错误句柄来返回错误和诊断信息。

4、OCIServerAttach()连接方式demo

#include <stdio.h>

#include <string.h>

#include <stdlib.h>

#include <malloc.h>

#include "DCI.h"

/*   声明句柄 */

OCIEnv          *envhp;             /*   环境句柄            */

OCISvcCtx       *svchp;             /*   服务环境句柄          */

OCIServer       *srvhp;             /*   服务器句柄           */

OCISession      *authp;             /*   会话句柄            */

OCIStmt         *stmthp;            /*   语句句柄            */

OCIDescribe     *dschp;             /*   描述句柄            */

OCIError        *errhp;             /*   错误句柄            */

OCIDefine       *defhp[3];          /*   定义句柄            */

OCIBind         *bidhp [4];         /*   绑定句柄            */

sb2             ind[3];             /*   指示符变量           */

/*   绑定select结果集的参数            */

text            szpersonid[11];     /*   存储personid列 */

text            szsex[2];           /*   存储sex列 */

text            szname[51];         /*   存储name列         */

text            szemail[51];        /*   存储mail列         */

text            szphone[26];        /*   存储phone列        */

char            sql[256];           /*   存储执行的sql语句*/

int main(int argc, char *argv[])

{

     int errcno;

     char errbuf[512]= "";

     sb4 errcode;

     char strServerName[50];

     char strUserName[50];

     char strPassword[50];

     /*    设置服务器,用户名和密码                  */

     strcpy(strServerName,"localhost");

     strcpy(strUserName,"SYSDBA");

     strcpy(strPassword,"SYSDBA");

      /* 初始化OCI应用环境*/

      OCIInitialize(OCI_DEFAULT, NULL, NULL, NULL, NULL);

      /* 初始化环境句柄            */

      OCIEnvInit(&envhp, OCI_DEFAULT,0, 0);

      /*   分配句柄             */

      OCIHandleAlloc(envhp, (dvoid**)&svchp, OCI_HTYPE_SVCCTX, 0, 0);              /*   服务器环境句柄  */

      OCIHandleAlloc(envhp, (dvoid**)&srvhp, OCI_HTYPE_SERVER, 0, 0);              /*   服务器句柄     */

      OCIHandleAlloc(envhp, (dvoid**)&authp, OCI_HTYPE_SESSION, 0, 0);            /*   会话句柄       */

      OCIHandleAlloc(envhp, (dvoid**)&errhp, OCI_HTYPE_ERROR, 0, 0);               /*   错误句柄       */

      OCIHandleAlloc(envhp, (dvoid**)&dschp, OCI_HTYPE_DESCRIBE,0,0);                   /*    描述符句柄    */

      /*   连接服务器    */

      OCIServerAttach(srvhp, errhp,(text *)strServerName, (sb4)strlen(strServerName),OCI_DEFAULT);

      /*   设置用户名和密码              */

      OCIAttrSet(authp,OCI_HTYPE_SESSION,(text *)strUserName,

           (ub4)strlen(strUserName),OCI_ATTR_USERNAME,errhp);

      OCIAttrSet(authp,OCI_HTYPE_SESSION,(text *)strPassword,

           (ub4)strlen(strPassword), OCI_ATTR_PASSWORD,errhp);

      /*   设置服务器环境句柄属性 */

      OCIAttrSet ((dvoid*)svchp, (ub4) OCI_HTYPE_SVCCTX,

           (dvoid*)srvhp, (ub4) 0, OCI_ATTR_SERVER, errhp);

      OCIAttrSet(svchp, OCI_HTYPE_SVCCTX,(dvoid*)authp,

           0, OCI_ATTR_SESSION, errhp);

      /*   创建并开始一个用户会话 */

      OCISessionBegin (svchp, errhp, authp,OCI_CRED_RDBMS,OCI_DEFAULT);

      OCIHandleAlloc(envhp, (dvoid**)&stmthp,OCI_HTYPE_STMT, 0, 0);                /*   语句句柄 */

      /************************************************************************/

      //结束会话

      OCISessionEnd(svchp, errhp, authp, (ub4) 0);

      //断开与数据库的连接

      OCIServerDetach(srvhp, errhp, OCI_DEFAULT);

      //释放OCI句柄

      OCIHandleFree((dvoid*)dschp, OCI_HTYPE_DESCRIBE);

      OCIHandleFree((dvoid*)stmthp, OCI_HTYPE_STMT );

      OCIHandleFree((dvoid*)errhp, OCI_HTYPE_ERROR);

      OCIHandleFree((dvoid*)authp, OCI_HTYPE_SESSION );

      OCIHandleFree((dvoid*)svchp, OCI_HTYPE_SVCCTX);

      OCIHandleFree((dvoid*)srvhp, OCI_HTYPE_SERVER);

      return 0;

 }

参考blog:https://www.cnblogs.com/Winnie-Z/articles/16264822.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
OCI 编程,可以通过 OCI 的 `OCILogon()` 或者 `OCILogon2()` 函数来建立到 Oracle 数据库的连接。这些函数需要传递一个 `OCISvcCtx` 结构体指针作为参数,同时需要填充 `OCIServer` 结构体、`OCIError` 结构体和 `OCIAuthInfo` 结构体等参数。 在 `OCISvcCtx` 结构体,需要填充 `OCIServer` 结构体指针和 `OCIError` 结构体指针。`OCIServer` 结构体指针表示连接的服务器信息,需要填充服务器的 IP 地址、端口号和 SID 等信息。`OCIError` 结构体指针表示连接过程出现的错误信息。 以下是一个示例代码,可以在 `OCILogon()` 函数传递 IP、port、SID、用户名和密码等参数: ``` OCIEnv* envhp; OCISvcCtx* svchp; OCIError* errhp; OCIServer* srvhp; OCIAuthInfo* authp; char* dbstr = "(DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=192.168.10.2)(PORT=21010))(CONNECT_DATA=(SID=test)))"; char* username = "test"; char* password = "test123"; OCIInitialize(OCI_DEFAULT, NULL, NULL, NULL, NULL); OCIHandleAlloc(envhp, (void**)&errhp, OCI_HTYPE_ERROR, 0, NULL); OCIServerAttach(srvhp, errhp, dbstr, strlen(dbstr), OCI_DEFAULT); OCIHandleAlloc(envhp, (void**)&authp, OCI_HTYPE_AUTHINFO, 0, NULL); OCIAttrSet(authp, OCI_HTYPE_AUTHINFO, username, strlen(username), OCI_ATTR_USERNAME, errhp); OCIAttrSet(authp, OCI_HTYPE_AUTHINFO, password, strlen(password), OCI_ATTR_PASSWORD, errhp); OCIHandleAlloc(envhp, (void**)&svchp, OCI_HTYPE_SVCCTX, 0, NULL); OCIAttrSet(svchp, OCI_HTYPE_SVCCTX, srvhp, 0, OCI_ATTR_SERVER, errhp); OCIAttrSet(svchp, OCI_HTYPE_SVCCTX, authp, 0, OCI_ATTR_AUTHINFO, errhp); OCILogon(envhp, errhp, &svchp, strlen(username), username, strlen(password), password, dbstr, strlen(dbstr)); // 连接成功后可以执行 SQL 查询等操作 OCIHandleFree(errhp, OCI_HTYPE_ERROR); OCIHandleFree(authp, OCI_HTYPE_AUTHINFO); OCIHandleFree(svchp, OCI_HTYPE_SVCCTX); OCIServerDetach(srvhp, errhp, OCI_DEFAULT); OCIHandleFree(srvhp, OCI_HTYPE_SERVER); ``` 其,`dbstr` 参数表示连接字符串,需要填写 IP、port、SID 等信息;`username` 和 `password` 参数表示连接的用户名和密码。在函数的最后需要释放分配的内存空间。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Bussy-Lake

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值