ZLW |
您所在的位置:网站首页 › 洛阳赋中洛神指谁 › ZLW |
OCI基础部分内容包含以下几部分内容: 头文件和Makefile位置 OCI编程概览 OCI数据结构 OCI编程步骤 错误处理 其他编程须知 OCI程序中使用PL/SQL OCI全球化支持 头文件和Makefile位置在Linux和UNIX系统中进行OCI和OCCI客户端程序开发所需要用到的OCI和OCCI头文件在$ORACLE_HOME/rdbms/public路径下。无论是Oracle数据库服务器安装还是Oracle管理或用户客户端安装,这些文件都是可用的。 所有示例程序以及其相关的头文件在$ORACLE_HOME/rdbms/public目录下。这些示例程序只能从Examples介质中安装。 Examples 11gr2的Examples安装包为linux_11gR2_examples.zip,从官网下载,并按照Oracle Database Examples Installation Guide中的安装包步骤进行安装即可。 关于Examples中的样例程序和各自的目的说明会在单独一个笔记中阐述。 demo路径下提供了若干makefiles文件,每个makefiles都包含注释来描述使用它编译可执行文件的使用方法说明。Oracle建议如果允许的话使用这些示例的makefile文件,以避免编译和连接过程中的错误。 demo路径下的demo_rdbms.mk文件是一个示例的makefile文件。阅读注释可知如何构建OCI样例程序。确保你自己定制的makefile文件中在INCLUDE路径信息中包含$ORACLE_HOME/rdbms/public路径。 ociucb.mk文件是一个构建调用共享库的样例makedile。 OCI编程概览OCI 应用程序的总体目标是代表多个用户进行操作。 在 n 层配置中,多个用户向客户端应用程序发送 HTTP 请求。 客户端应用程序可能需要执行一些数据操作,包括交换数据和进行数据处理。 OCI使用下面的工作流: 通过初始化OCI编程环境和线程创建环境。 分配必要的句柄,创建到服务器的连接和用户会话 通过在服务器商执行SQL语句实现与数据库服务器的数据交换,以及执行必要额应用段数据处理 执行prepared语句或重新prepare一个语句以备执行 结束用户会话,断开与服务器的连接 释放句柄和数据结构 下图描述了一个OCI应用的步骤流程:![]() 句柄和描述符是OCI应用中经常用到的不透明数据结构。它们可用通过调用特殊分配函数被直接分配,也可以通过OCI函数隐式地进行分配。 句柄和描述符存储与数据、连接或应用程序行为有关的信息。 下一节将更详细地定义句柄。 句柄几乎每个OCI调用的参数列表中都会包含一个或多个句柄。一个句柄就是一个指向由OCI库分配的存储空间的不透明指针。应用可以使用句柄存储上下文或连接信息,例如环境或服务上下文句柄,也可以存储OCI函数或数据的信息,例如错误或describe句柄。句柄让编程变得简单,因为是使用库来维护数据而非应用来维护数据。 大多数OCI应用必须要获取存储在句柄中的信息,所以设计通过set和get属性的OCI调用,OCIAttrGet()和OCIAttrSet()来访问或设置这些信息。 下表列出了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 不适用 分配和释放句柄除了绑定、定义、线程句柄之外,其他句柄的分配都是针对一个特定环境句柄来说的。在执行分配句柄的调用时,需要将环境句柄作为参数之一传入,因此分配的句柄是特定于一个环境的。 绑定和定义句柄是特定于语句句柄分配的,其中包含语句句柄所代表的语句的一些信息。 绑定和定义局部由OCI库隐式地分配,不需要用户分配。 环境句柄由OCIEnvCreate()或OCIEnvNlsCreate()的调用完成分配和初始化。任何一个OCI应用都需要用到这两个函数中的一个。 所有用户分配的句柄的初始化都通过调用OCI句柄分配函数OCIHandleAlloc()来完成。 句柄的类型包括:会话池句柄,直接路径上下文句柄,线程句柄,COR句柄,订阅句柄,描述句柄,语句句柄,服务上下文句柄,错误句柄,服务器句柄,连接池句柄,HA事件句柄,管理句柄。 线程句柄通过OCIThreadHndInit()调用进行分配。 所有应用必须释放不再使用的句柄,释放句柄的通过OCIHandleFree()完成。 注意: 当一个母句柄释放,所有与其关联的子句柄都将一并释放并且不能再被使用。例如一个语句句柄被释放后,任何与其相关的绑定句柄和定义句柄都会一并释放。 句柄减少了对全局变量的需求,同时简化了错误报告,可以使用一个错误句柄来返回错误和诊断信息。 环境句柄环境句柄定义了一个包含所有OCI函数的上下文。每个环境句柄包含一个允许快速内存访问的内存缓存区域。所有在该环境句柄下的内存分配都是从缓存区域分配的。如果多个线程试图在同一个环境句柄下分配内存,则对缓存区域的访问是序列化的。当多个线程共享一个环境句柄时,在访问缓存时可能会发生阻塞。 除绑定和定义句柄是隐式分配的,其他句柄的分配在调用OCIHandleAlloc()函数时将环境句柄作为母句柄参数传入。 错误句柄大多数OCI调用中会将错误句柄作为一个参数。错误句柄维护OCI操作期间发生的错误信息。如果一个调用过程中发生错误,可以将错误句柄传递给OCIErrorGet()来获取更多错误发生时的相关信息。 分配错误句柄时在一个OCI应用中第一步需要完成的内容之一,因为大多数OCI调用需要使用一个错误句柄做参数。 服务上下文句柄及其相关句柄服务上下文句柄定义了确定 OCI 调用服务器的操作上下文的属性。 服务上下文句柄包含三个句柄作为其属性,分别代表服务器连接、用户会话和事务。句柄之间的关系如下图描述:
语句句柄是标识一个SQL或PL/SQL语句及其相关连属性的上下文。
描述符句柄在OCI描述函数OCIDescribeAny()调用时使用。这个调用函数用于获取数据库中schema对象相关信息(例如,函数或存储过程)。这个调用使用一个描述句柄作为一个参数,同时传入被描述的对象信息。调用完成后,描述句柄被对象信息所填充。届时OCI应用程序可以通过参数描述符的属性获取描述信息。 复杂对象检索(COR)句柄一些处理 Oracle 数据库中对象的 OCI 应用程序使用复杂对象检索 (COR) 句柄。 此句柄包含 COR 描述符,这些描述符提供用于检索被其他对象引用的对象的指示。 线程句柄线程句柄在多线程环境中使用,更多信息参阅OCITthreadPackage。 订阅句柄订阅句柄由注册和订阅接收数据库事件通知或 AQ 命名空间事件通知的 OCI 客户端应用程序使用。订阅句柄封装了所有与客户注册相关的信息。 直接路径句柄对于使用 Oracle 数据库直接路径加载引擎的 OCI 应用程序,直接路径句柄是必需的。 直接路径加载接口使得应用程序能够访问 Oracle 数据库的直接块格式化程序。下图显示了不同种类的直接路径句柄。
连接池句柄用于通过调用特定 OCI 函数将物理连接池化为虚拟连接的应用程序。 句柄属性所有OCI句柄都有代表其中存储的数据的属性。用户可以通过调用获取属性的函数OCIAttrGet()来读取句柄属性,通过调用设置属性的函数OCIAttrSet()来修改句柄属性。 例如,下面例子中通过写入OCI_ATTR_USERNAME属性来设置会话句柄的用户名。 text username[] = "hr"; err = OCIAttrSet ((void *) mysessp, OCI_HTYPE_SESSION, (void *)username, (ub4) strlen((char *)username), OCI_ATTR_USERNAME, (OCIError *) myerrhp);有些OCI函数在调用前,需要先设置好特定的句柄属性。例如,当调用OCISessionBegin()建立一个用户登录会话时,在调用前用户会话句柄上必须设置好用户名和密码。 其他OCI函数则在调用完成后返回有用的数据到句柄属性中。例如,当调用OCIStmtExecute()执行一个SQL查询时,与select列表相关联的描述信息被返回到语句句柄中,如下所示。 ub4 parmcnt; /* get the number of columns in the select list */ err = OCIAttrGet ((void *)stmhp, (ub4)OCI_HTYPE_STMT, (void *) &parmcnt, (ub4 *) 0, (ub4)OCI_ATTR_PARAM_COUNT, errhp); OCI描述符OCI描述符和定位符是维护特定数据信息的不透明数据结构。下表列出描述符和定位符类型以及其对应的C数据类型和调用OCIDescriptorAlloc()分配描述符时指定类型用的OCI类型常量。释放描述符和定位符使用OCIDescriptorFree()函数。 描述 C数据类型 OCI类型常量 快照描述符 OCISnapshot OCI_DTYPE_SNAP 结果集描述符 OCIResult OCI_DTYPE_RSET LOB数据类型定位符 OCILobLocator OCI_DTYPE_LOB BFILE数据类型定位符 OCILobLocator OCI_DTYPE_FILE 只读参数描述符 OCIParam OCI_DTYPE_PARAM ROWID描述符 OCIRowid OCI_DTYPE_ROWID ANSI DATE描述符 OCIDateTime OCI_DTYPE_DATE TIMESTAMP描述符 OCIDateTime OCI_DTYPE_TIMESTAMP TIMESTAMP WITH TIME ZONE描述符 OCIDateTime OCI_DTYPE_TIMESTAMP_TZ TIMESTAMP WITH LOCAL TIME ZONE描述符 OCIDateTime OCI_DTYPE_TIMESTAMP_LTZ INTERVAL YEAR TO MONTH描述符 OCIInterval OCI_DTYPE_INTERVAL_YM INTERVAL DAT TO SECOND描述符 OCIInterval OCI_DTYPE_INTERVAL_DS 用户回调描述符 OCIUcb OCI_DTYPE_UCB 注册请求中不同数据库服务器名 OCIServerDNs OCI_DTYPE_SRVDN 复杂对象描述符 OCIComplexObjectComp OCI_DTYPE_COMPLEXOBJECTCOMP 高级队列入队操作 OCIAQEnqOptions OCI_DTYPE_AQENQ_OPTIONS 高级队列出队操作 OCIAQDeqOptions OCI_DTYPE_AQDEQ_OPTIONS 高级队列信息参数 OCIAQMsgProperties OCI_DTYPE_AQMSG_PROPERTIES 高级队列代理 OCIAQAgent OCI_DTYPE_AQAGENT 高级队列通知 OCIAQNotify OCI_DTYPE_AQNFY 高级队列监听选项 OCIAQListenOpts OCI_DTYPE_AQLIS_OPTIONS 高级队列信息参数 OCIAQLisMsgProps OCI_DTYPE_AQLIS_MSG_PROPERTIES 变更通知 None OCI_DTYPE_CHDES 表变更 None OCI_DTYPE_TABLE_CHES 列变更 None OCI_DTYPE_ROW_CHES注意: 尽管对于LOB类型只有一个C数据类型OCILobLocator,但是内部LOB类型和外部LOB类型在分配定位符的时候指定的OCI类型常量是不同的。 每种描述符的主要作用如下,后续做详细描述 OCISnapshot——语句执行中使用 OCILobLocator——用于LOB(OCI_DTYPE_LOB)或者BFILE(OCI_DTYPE_FILE)调用 OCIParam——用于描述相关调用 OCIRowid——用于绑定或定义ROWID值 OCIDateTime和OCIInterval——用于日期和间隔类型 OCIComplexObjectComp——用于复杂对象检索 OCIAQEnqOptions,OCIAQDeqOptions,OCIAQMsgProperties,OCIAgent——用于高级队列 OCIAQNotify——用于发布订阅通知 OCIServerDNs——用于发布基于LDAP的订阅通知 快照描述符在调用执行语句函数OCIStmsExecute()时,快照描述符是一个可选参数。它表示一个查询在代表数据库某个事件状态的快照中执行。 通过调用OCIDescriptorAlloc()时传入OCI_DTYPE_SNAP作为类型参数分配快照描述符。 LOB和BFILE定位符大对象(LOB)类型是一种可以存储二进制大对象或字符大对象的Oracle数据类型。在数据库中,一个数据行的LOB列中或者一个对象的LOB属性中,存储的是一个叫做LOB定位符的不透明数据结构。定位符可以理解为是一个指向独立存储在另一个位置的真正LOB数据的指针。 注意: 用户可以根据应用来选择用或不用LOB定位符。用户也可以使用不需要指定LOB定位符的LOB数据接口。在数据接口中用户可以为CLOB类型绑定或定义字符数据,为BLOB绑定或定义RAW数据。 OCILOB定位符用于在LOB(BLOB或CLOB)或FILE(BFILE)上指向OCI操作。OCILobXXX函数使用LOB定位符而非LOB值做参数。OCILOB函数不使用LOB数据作为参数,它们使用LOB定位符做参数并操作定位符指向的LOB数据。 通过调用OCIDescriptorAlloc()函数并传入OCI_DTYPE_LOB作为类型参数来为BLOB或CLOB数据分配LOB定位符,通过传入OCI_DTYPE_FILE作为类型参数来为BFILE数据分配LOB定位符。 注意: 两种LOB定位符不能内部互转。当绑定或定义BLOB或CLOB数据时,应用必须注意定位符是使用OCI_DTYPE_LOB作为类型参数分配的。同样的,当绑定或定义BFILE数据时,应用必须注意定位符是使用OCI_DTYPE_FILE作为类型参数分配的。 OCI应用可以通过执行一个select列表中包含LOB列或LOB属性的SQL语句从数据库中检索LOB定位符。这种情景下,应用需要首先分配LOB定位符,然后使用这个LOB定位符定义一个输出变量。类似地,LOB定位符也可以用于绑定操作,在SQL语句占位符和一个LOB类型数据之间建立联系。 参数描述符OCI 应用程序使用参数描述符来获取select列表的列信息或模式对象的信息。 该信息可以通过一个describe操作获取到。 参数描述符是唯一一个不通过OCIDescriptorAlloc()函数分配的描述符类型。只能通过调用OCIParamGet()函数指定参数位置,作为一个描述符句柄或语句句柄的属性,或通过一个复杂对象检索句柄来获取参数描述符。 ROWID描述符ROWID描述符用于需要检索和使用Oracle ROWID类型数据的应用。为了使用ROWID类型,应用需为SQL的lelect列表中的rowid位置定义一个ROWID描述符,然后将ROWID数据获取到这个描述符中。这个描述符可以在之后绑定到一个INSERT语句或WHERE子句的输入变量上。 也可以通过在执行后的语句句柄上调用OCIAttrGet()将ORWID重定向到描述符中。 Date,Datetime,Interval描述符日期、时间以及间隔描述符在使用日期、时间或间隔数据类型(OCIDate,OCIDateTime,OICInterval)的应用程序中会用到。 这些描述符可以用于绑定和定义。可以作为参数传递给OCIDescriptorAlloc()和OCIDescriptorFree(),来完成内存的分配和释放。 复杂对象描述符当处理对象数据时,使用复杂对象检索(COR)可以提升应用性能。 高级队列描述符Oracle Streams Advanced Queuing 提供消息队列作为 Oracle 数据库的一个集成部分。 用户内存分配OCIDescriptorAlloc()函数参数列表中有一个xtramem_sz参数。这个参数用于指定与一个描述符或定位符一起分配的用户内存的大小。 通常来说,应用使用这个参数分配一个与描述符或定位符具有相同生命周期的应用自定义数据结构。这个结构可以用于应用程序统计或存储上下文信息。 使用xtramem_sz参数意味着当每个描述符或定位符被分配或释放时,应用不需要显式地分配和释放对应自定义结构的内存。这部分用户数据结构的内存会随着描述符或定位符的分配而分配,随着描述符或定位符的释放而释放。 OCIHandleAlloc()也有一个类似的参数,允许分配与句柄有相同生命周期的用户内存。 OCIEnvCreate()和(OCIEnvInit()以弃用)也有一个类似的参数,允许分配与环境句柄有相同生命周期的用户内存。 OCI编程步骤本部分内容详细描述开发OCI应用程序的每一个步骤。其中有些步骤是可选的。例如,如果要执行的语句不是查询语句,则不需要对select列表中的内容进行描述和定义。 下面几个部分描述了OCI应用需要的步骤 OCI环境初始化 在OCI中执行SQL语句 提交或回滚操作 结束应用 OCI中的错误句柄 在这些OCI函数步骤之间也会有其他应用特定的处理。 OCI环境初始化这部分内容描述如何初始化OCI环境,创建到服务器的连接以及授权用户以执行数据库操作。 初始化OCI环境主要包含以下三个步骤: 创建OCI环境 分配句柄和描述符 应用初始化,连接以及建立会话 创建OCI环境每一个OCI函数的调用都需要在一个由OCIEnvCreate()创建的环境上下文中中进行。因此必须在执行任何其他OCI调用之前调用OCIEnvCreate()。唯一的例外是为OCI共享模式设置进程级属性。 OCIEnvCreate()的mode参数指定应用调用OCI库函数的时候是否能: 在线程环境中允许(mode=OCI_THREADED) 使用对象(mode=OCI_OBJECT)。使用AQ订阅注册 使用订阅(mode=OCI_EVENTS) mode可以在每一个环境中独立设置。 如果应用绑定和定义了对象或者使用了OCI对象导航相关的调用,初始化为object mode是非常必要的。除上面列出的三种功能外,应用程序也可以选择其他模式(mode=OCI_DEFAULT),或者上面三种的组合用一个竖线分割两种模式。例如,如果设置mode=(OCI_THREADED | OCI_OBJECT),应用可以允许在一个线程化的环境中,并且可以使用对象。 用户可以为每一个OCI环境指定用户自定义的内存管理函数。 分配句柄和描述符Oracle 数据库提供分配、释放句柄和描述符的OCI函数。在将句柄作为参数传递给其他OCI函数前,首先需要使用OCIHandleAlloc()分配该句柄,除非这个OCI函数分配句柄,例如OCIBindByPos()。 用户可以基于应用的功能需求,使用OCIHandleAlloc()分配句柄模块的表中列出的部分或所有类型的句柄。 应用初始化,连接以及建立会话应用程序必须调用 OCIEnvNlsCreate() 来初始化 OCI 环境句柄。 现有应用程序可能已使用 OCIEnvCreate()。 应用程序与Oracle数据库建立连接并开启一个用户会话需要遵循以下几个步骤: 单个用户,单个连接 客户端通过代理访问 非代理的多会话或多连接注意: 建议开发应用时使用 OCIEnvCreate() 或 OCIEnvNlsCreate() 代替 OCIIInitialize() 和 OCIEnvInit() 。OCI仅为了兼容旧版支持OCIInitialize() 和 OCIEnvInit() 。 单个用户,单个连接单个用户单个连接这种是最简单的登录方式,可以在应用对每个数据库连接仅维护一个用户会话的情况下使用 当应用调用OCILogon2()或OCILogon()时,OCI库对传递给它的服务上下文句柄进行初始化,为发请求的用户创建到指定Oracle数据库的连接。 下面例子是调用OCILogon2(),为用户名为hr密码为hr的用户创建到数据库oracledb的单个会话的使用方式: OCILogon2(envhp, errhp, &svchp, (text *)"hr", (ub4)strlen("hr"), (text *)"hr", (ub4)strlen("hr"), (text *)"oracledb", (ub4)strlen("oracledb"), OCI_DEFAULT);OCILogon2()这个函数的参数包含服务上下文句柄(通过调用该函数完成了初始化),用户名,密码,用于建立连接的数据库名。最后一个参数mode设置为OCI_DEFAULT时与调用OCILogon()函数的效果是一样的。在这个函数中服务器和用户会话句柄都被隐式地分配。建议新的应用都使用OCILogon2()。 如果应用使用单用户单连接的登录方式,服务上下文句柄,服务器句柄和用户会话句柄都是只读的。以你关于程序不能通过调用OCIAttrSet()改变服务上下文的特定属性来切换会话或事务。 使用OCILogon2()初始化会话和授权的应用必须使用OCILogoff()来结束它们。 注意: 为简化演示此功能,此示例没有使用生产系统通常使用的密码管理技术。 在生产环境中,遵循 Oracle 数据库密码管理指南,并禁用任何示例帐户。 有关密码管理指南和其他安全建议,请参阅 Oracle Database Security Guide。 客户端通过代理访问(待补充)代理身份验证通常是在具有中间层(例如防火墙)的环境中使用的过程,其中最终用户向中间层进行身份验证,然后中间层代表用户作为其代理向数据库进行身份验证。 中间层以代理用户身份登录数据库。 代理用户可以切换身份,并在登录数据库后切换到最终用户的身份。 它可以使用与特定最终用户相匹配的授权,代表最终用户执行操作。 OCI 和 ALTER USER 语句支持对数据库用户的代理,其 BNF 语法为: ALTER USER GRANT CONNECT THROUGH [AUTHENTICATION REQUIRED];ALTER USER 语句在应用程序中使用一次。 之后可以进行多次连接。 在 OCI 中,用户可以使用连接字符串或调用函数 OCIAttrSet()并传入参数OCI_ATTR_PROXY_CLIENT 。 非代理的多会话或多连接非代理多会话或连接方式,通过显式地添加和调用启用会话函数来维护一个数据库连接上的多个用户会话和连接。 附加到 Oracle 数据库和开始会话的特定函数有: OCIServerAttach()——为OCI操作创建到Oracle数据库地访问路径 OCISessionBegin()——为用户创建到特定Oracle数据库的会话。这个函数对于需要在Oracle数据库上执行操作的用户来说是必须的。再次调用OCISessionBegin()时使用不同的服务上下文句柄和会话上下文句柄会导致前一个用户登出,并引发错误。要想同时运行两个不可互相替代的会话,第二次调用OCISessionBegin()函数时必须指定一个相同的服务上下文句柄和一个新的会话上下文句柄。 下面例子描述了一个OCI环境的创建和初始化过程: 创建了一个服务器上下文并设置到服务句柄中 然后使用一个数据库客用户名和密码创建并初始化了一个用户会话句柄 为了简化流程,错误处理部分没有在代码中体现 #include ... main() { ... OCIEnv *myenvhp; /* the environment handle */ OCIServer *mysrvhp; /* the server handle */ OCIError *myerrhp; /* the error handle */ OCISession *myusrhp; /* user session handle */ OCISvcCtx *mysvchp; /* the service handle */ ... /* initialize the mode to be the threaded and object environment */ (void) OCIEnvCreate(&myenvhp, OCI_THREADED|OCI_OBJECT, (void *)0, 0, 0, 0, (size_t) 0, (void **)0); /* allocate a server handle */ (void) OCIHandleAlloc ((void *)myenvhp, (void **)&mysrvhp, OCI_HTYPE_SERVER, 0, (void **) 0); /* allocate an error handle */ (void) OCIHandleAlloc ((void *)myenvhp, (void **)&myerrhp, OCI_HTYPE_ERROR, 0, (void **) 0); /* create a server context */ (void) OCIServerAttach (mysrvhp, myerrhp, (text *)"inst1_alias", strlen ("inst1_alias"), OCI_DEFAULT); /* allocate a service handle */ (void) OCIHandleAlloc ((void *)myenvhp, (void **)&mysvchp, OCI_HTYPE_SVCCTX, 0, (void **) 0); /* set the server attribute in the service context handle*/ (void) OCIAttrSet ((void *)mysvchp, OCI_HTYPE_SVCCTX, (void *)mysrvhp, (ub4) 0, OCI_ATTR_SERVER, myerrhp); /* allocate a user session handle */ (void) OCIHandleAlloc ((void *)myenvhp, (void **)&myusrhp, OCI_HTYPE_SESSION, 0, (void **) 0); /* set user name attribute in user session handle */ (void) OCIAttrSet ((void *)myusrhp, OCI_HTYPE_SESSION, (void *)"hr", (ub4)strlen("hr"), OCI_ATTR_USERNAME, myerrhp); /* set password attribute in user session handle */ (void) OCIAttrSet ((void *)myusrhp, OCI_HTYPE_SESSION, (void *)"hr", (ub4)strlen("hr"), OCI_ATTR_PASSWORD, myerrhp); (void) OCISessionBegin ((void *) mysvchp, myerrhp, myusrhp, OCI_CRED_RDBMS, OCI_DEFAULT); /* set the user session attribute in the service context handle*/ (void) OCIAttrSet ((void *)mysvchp, OCI_HTYPE_SVCCTX, (void *)myusrhp, (ub4) 0, OCI_ATTR_SESSION, myerrhp); ... }样例路径下的样例程序cdemo81.c中有对该过程包含错误处理的完整描述。 在OCI中执行SQL语句第 4 章概述了在 OCI 中处理 SQL 语句所涉及的具体步骤。 提交或回滚操作应用通过调用OCITransCommit()向数据库提交变更。这个函数使用一个服务上下文句柄作为参数之一。要提交变更的事务与服务上下文相关联。事务可以被应用显式地创建,也可以在执行数据库修改地时候隐式地创建。 回滚事务可以调用OCITransRollback()。 如果应用还未调用OCITransCommit()就以非正常登出的方式断开连接,例如失去网络连接,所有活动的事务都会被自动回滚。 结束应用一个OCI应用在结束前,需要执行以下步骤: 每个会话都调用OCISessionEng(),删除每个用户会话 每个数据源都调用OCIServerDetach(),删除到数据源的访问 每个句柄都调用OCIHandleFree(),显式地释放所有句柄 删除环境句柄,该操作会同时释放所有与环境句柄相关联地其他句柄 OCIServerDetach()和OCISessionEnd()的调用不强制必须执行,但建议最好执行。如果应用结束但是没有调用OCITransCommit()没有被调用,则所有未结束的事务会自动回滚。 OCI中的错误句柄OCI函数有一组返回代码代表调用结果,这些返回代码可以表示调用成功还是失败,如OCI_SUCCESS或OCI_ERROR,也可以表示其他应用程序可能需要的状态信息,有OCI_NEED_DATA或OCI_STILL_EXECUTING。大多数OCI调用都会返回一种代码。 应用可以检查服务器句柄中的OCI_ATTR_SERVER_STATUS属性的值来确认到服务器的连接没有因OCI_ERROR而终结。如果属性的值为OCI_SERVER_NOT_CONNECTED,那么必须重新建立到服务器的连接和用户会话。 OCI中的返回错误代码见下表: OCI返回码 描述 OCI_SUCCESSS 函数执行成功 OCI_SUCCESS_WITH_INFO 函数执行成功,调用OCIErrorGet()可以得到更多诊断信息,可能存在警告信息 OCI_NO_DATA 函数执行完成,没有更多数据可以返回了 OCI_ERROR 函数执行失败,调用OCIErrorGet()可以返回更多信息 OCI_INVALID_HANDLE 错误句柄作为参数传入了,或者用户回调传入了错误的句柄或上下文。没有更多诊断信息 OCI_NEED_DATA 应用程序必须提供运行时数据 OCI_STILL_EXECUTING 以非阻塞模式创建的服务上下文,当前操作无法立即执行。要完成该操作需要重新调用一次当前操作。OCIErrorGet()返回ORA-03123作为错误码 OCI_CONTINUE 只有回调函数才会返回这个结果码。表示回调函数需要OCI库回复其正常处理如果返回码显式发生了错误,应用程序可以调用OCIErrorGet()获取错误码和数据库的特定信息。OCIErrorGet()要传入的参数之一就是引发错误的错误句柄。 注意: 可以重复调用OCIErrorGet()获取多个诊断记录,直到没有更多可返回的记录(返回OCI_NO_DATA)。OCIErrorGet()至少返回一条诊断记录。 数据相关的返回码和错误码如下表所示,当获取的数据是正常、空值或截断时,对应的OCI返回码、错误号、指示符变量和列返回码。 表待补充。 返回其他值的函数有些函数不反悔OIC错误码,而是返回其他值。使用这些函数时,需要注意它们直接通过函数调用返回值,而不是通过OUT参数。关于每个函数及其返回值的更多详细信息参阅引用章节。 其他编程指导 操作系统相关考量操作系统可能提供允许派生子进程重用母进程创建的状态的功能。在派生了一个子进程后,子进程不能使用母进程创建的同一个数据库连接。子进程使用与父进程相同的数据库连接的任何尝试都可能导致不希望的连接干扰并导致间歇性 ORA-03137 错误,因为 Oracle Net 期望只有一个用户进程使用与数据库的连接。 如果需要多个并发连接,当平台支持线程包时,建议考虑使用线程。 单线程或多线程应用程序都支持并发连接。 对于许多并发打开连接的情况,可以考量使用连接池来提高性能。 参数类型OCI函数使用大量的不同类型的参数,包含整数,句柄,字符串等。对于其中一些类型的参数需要特别关注。具体参照本章节的后续阐述。 地址类型参数地址类型参数用于将变量的地址传递给Oracle数据库。当使用C语句开发的时候,需要特别注意,因为C语言中通常是传递标量参数的值。 整型参数二进制整数和短二进制整数类型参数的大小取决于系统。用户需查阅特定操作系统的Oracle数据库文档来确定所使用操作系统中这类整型的大小。 字符串参数字符串类型是地址类型参数中的特殊一类。每个允许传入一个字符串类型做参数的OCI函数都会同时有一个字符串长度参数。长度参数应设置为爱风尘的长度。 往列中插入空值往数据库列中插入一个空值可以有以下几种方式: 第一种方法是在INSERT或UPDATE语句中使用NULL字面量。INSERT INTO emp(ename, empno,deptno) VALUES(NULL,100,200); 第二种方法是在OCI绑定调用种使用指示符变量 第三种方法是在一个绑定的调用中,将缓冲区长度和最大长度参数都设置为0 指示符变量对于一个DML语句,一个PL/SQL语句或一个查询语句而言,每个OCI绑定和定义调用都有一个与指示符变量或指示符变量数组相关联的参数。 C语言没有空值的概念,因此,用户需要将指示变量与输入变量关联以指定对应的占位符是否为 NULL。 当数据传递到 Oracle 数据库时,这些指示变量的值决定是否将 一个数据库字段设置为NULL。 对于输出变量,指示符变量决定从Oracle返回的值是NULL还是被截断的值。如果OCIStmtFetch2()调用获取NULL值或者OCIStmtExecute()调用发生截断,OCI调用将会返回OCI_SUCCESS_WITH_INFO。 指示符变量的数据类型是sb2。对于指示符变量数组来说,每个数组元素应该是sb2类型。 输入指示符变量对于输入的主机变量来说,OCI应用允许指示符变量设置为下面的值: 输入指示符变量的值 Oracle数据库的行为 -1 Oracle数据库将对应列设置为NULL,忽略输入变量的值 >=0 Oracle数据库将对应的列设置为输入变量的值 输出指示符变量对于输出变量的指示符变量,Oracle数据库可以将指示符变量设置为以下值: 输出指示符变量的值 含义 -2 返回的数据长度超过输出变量的长度;数据被截断。此外,原始长度超过sb2 指示符变量可返回的最大数据长度 -1 查询的值为空,输出变量没有发生改变 0 Oracle数据库将一个完整的值返回给主机变量 >0 返回的数据长度超过输出变量的长度;数据被截断。指示符变量中的正值表示截断前的数据的实际长度 命名数据类型和REFs的指示符变量在8.0之后的版本中,大多数数据类型的指示符变量都如之前所描述的。唯一的例外是SQLT_NTY(一个命名的数据类型)。对于数据类型SQLT_NTY,指示符变量必须是一个指向指示符结构的指针。SQLT_REF数据类型与其他变量类型一样,都使用一个标准的标量指示符。 当使用对象类型转换器 (OTT) 将数据库类型转换为 C 结构表示时,将为每个对象类型生成一个空指示符结构。 此结构包括一个原子空指示符,以及每个对象属性的指示符。 取消调用待补充 定位更新和删除待补充 保留字待补充 OCI中的轮询模式操作OCI中有一些通过轮询模式完成的函数调用。这类轮询模式的调用函数有: 非阻塞模式的OCI调用 对 LOB 数据进行分段操作的 OCI 函数,例如OCILobRead2()和OCILobWrite2() 与OCIStmtSetPieceInfo()和OCIStmtGetPieceInfo()一起使用的OCIStmtExecute和OCIStmtFetch2() 在这种情况下,OCI 要求应用程序确保在连接上重复相同的 OCI 调用,并且在此期间连接上不执行任何其他操作。 在此类连接上执行任何其他 OCI 调用(当 OCI 将控制权交还给调用者时)可能会导致未知的行为。 因此,使用这种轮询模式的 OCI 调用,调用者必须确保在连接上重复相同的调用,并且在调用完成之前不进行任何其他操作。 但这种规则对OCIBreak()和OCIReset()不适用,调用者可以使用这两个函数停止一个已经开始OCI调用函数。 OCI中的非阻塞模式待补充 设置阻塞模式待补充 取消一个非阻塞调用待补充 在OCI程序中使用PL/SQL待补充 OCI全球化支持待补充 |
CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3 |