前言

在搭建tns310抓包的环境, 服务端是oracle8.1.7.4(从oracle8.1.7.0打了p2376472_8174_WINNT.zip补丁升级来的, 这补丁google了好久…, 不打补丁,用高版本的OCI连上oracle8i有问题,没那么多时间去实验,我信了, 直接上补丁)。

客户端试了几个(oracle9i, oracle10g, oracle11gr2), 在执行select语句之外的SQL, 总会得到ORA-24333的报错, 因为服务端已经定下来了, 没办法换(要不就不是tns310了),一直在试oracle客户端. 一执行select之外的SQL, 就得到ORA-24333报错. 正经活都没开始呢,前置任务就搞了这么久, 真悲伤。

因为测试程序是以前写好的,在服务端和客户端都是oracle11gr2时,都正常的。也不会怀疑是代码写挫了。一直在怀疑高版本oracle_client连接低版本oracle_client,是否有服务端或客户端配置上的问题。

验证失败一会,就开始找资料。再做实验,再失败,再找资料。直到看到csdn上一篇写于2016年9月的博客,才知道代码写错了…。

OCIStmtExecute的参数4是SQL语句的执行次数, 如果是select语句,次数可以为0, 因为后续还可以OCI去拿结果集,不用指定执行次数. 如果是非select语句,值不能为0,至少为1(至少执行一次).

其实问题解决后,再对照报错信息,感觉报错信息离报错点挺近的。
如果OCI编程没搞那么细致,特别是在高版本的OCI环境下实验正常,根本不会怀疑是代码写挫了. 因为执行的SQL语句数组不同,我也不敢肯定是不是原来的代码写对了. 以后有时间再实验,今天收工了。解决这个问题用了3天,杯具。

其实也有环境配置的问题(oracle8.1服务端,oracle客户端9i, 10g)(网络配置问题,用户权限问题,补丁问题). 本来用9i做最初的客户端实验,想着9i离8i不远,可能兼容性更好, 谁想弄出这些事。时间有限,这些曾经出现的问题得等有时间时再验证了.

实验成功的环境配置

服务端: win2k_server_sp4 + oracle8i + p2376472_8174_WINNT.zip. 重新设置了scott用户的权限(加了system权限)
客户端:win10x64 + oracle10.2.0.1.0

修正后的代码片段

        // 准备SQL语句sw_rc = OCIStmtPrepare(h_oci_stmt, h_oci_error, ora_text_select, (ub4)strlen((const char*)ora_text_select), (ub4)OCI_NTV_SYNTAX, (ub4)OCI_DEFAULT);if (OCI_SUCCESS != sw_rc) {// ora10通过sid连接ora8.1, 执行除了select语句之外的SQL, 都会得到下列错误// ORA-24333: 零迭代计数print_oci_error("error : OCIStmtPrepare", h_oci_error);break;}// 必须在执行SQL语句前, 获取SQL语句类型用于处理参数4, 防止出现错误 : ORA-24333: zero iteration countsw_rc = OCIAttrGet(h_oci_stmt, OCI_HTYPE_STMT, &stmt_type, NULL, OCI_ATTR_STMT_TYPE, h_oci_error);if (OCI_SUCCESS != sw_rc) {print_oci_error("error : OCI_ATTR_STMT_TYPE", h_oci_error);break;}// 执行SQLprintf("sw_rc = OCIStmtExecute(h_oci_context, h_oci_stmt, h_oci_error, (ub4)0, (ub4)0, (OCISnapshot*)0, (OCISnapshot*)0, OCI_DEFAULT);\r\n");// 处理参数4, 防止报错; ORA-24333sw_rc = OCIStmtExecute(h_oci_context, h_oci_stmt, h_oci_error, (ub4)(OCI_STMT_SELECT == stmt_type ? 0 : 1), (ub4)0, (OCISnapshot*)0, (OCISnapshot*)0,OCI_DEFAULT);// packet 27~29if (OCI_SUCCESS != sw_rc) {print_oci_error("error : OCIStmtExecute", h_oci_error);break;}

oracle官方的API帮助

OCIStmtExecute()
Purpose
This call associates an application request with a server.Syntax
sword OCIStmtExecute ( OCISvcCtx           *svchp,OCIStmt             *stmtp,OCIError            *errhp,ub4                 iters,ub4                 rowoff,CONST OCISnapshot   *snap_in,OCISnapshot         *snap_out,ub4                 mode );
Parameters
svchp (IN/OUT)
Service context handle.stmtp (IN/OUT)
An statement handle. It defines the statement and the associated data to be executed at the server. It is invalid to pass in a statement handle that has bind of data types only supported in release 8.x or later when svchp points to an Oracle7 server.errhp (IN/OUT)
An error handle you can pass to OCIErrorGet() for diagnostic information in the event of an error.iters (IN)
For non-SELECT statements, the number of times this statement is executed is equal to iters - rowoff.For SELECT statements, if iters is nonzero, then defines must have been done for the statement handle. The execution fetches iters rows into these predefined buffers and prefetches more rows depending upon the prefetch row count. If you do not know how many rows the SELECT statement will retrieve, set iters to zero.This function returns an error if iters=0 for non-SELECT statements.Note:
For array DML operations, set iters <= 32767 to get better performance.rowoff (IN)
The starting index from which the data in an array bind is relevant for this multiple row execution.snap_in (IN)
This parameter is optional. if supplied, must point to a snapshot descriptor of type OCI_DTYPE_SNAP. The contents of this descriptor must be obtained from the snap_out parameter of a previous call. The descriptor is ignored if the SQL is not a SELECT. This facility allows multiple service contexts to ORACLE to see the same consistent snapshot of the database's committed data. However, uncommitted data in one context is not visible to another context even using the same snapshot.snap_out (OUT)
This parameter optional. if supplied, must point to a descriptor of type OCI_DTYPE_SNAP. This descriptor is filled in with an opaque representation which is the current ORACLE "system change number" suitable as a snap_in input to a subsequent call to OCIStmtExecute(). This descriptor should not be used longer than necessary in order to avoid "snapshot too old" errors.mode (IN)
The modes are:OCI_BATCH_ERRORS - See "Batch Error Mode for OCIStmtExecute()", for information about this mode.
OCI_COMMIT_ON_SUCCESS - When a statement is executed in this mode, the current transaction is committed after execution, provided that execution completes successfully.
OCI_DEFAULT - Calling OCIStmtExecute() in this mode executes the statement. It also implicitly returns describe information about the select-list.
OCI_DESCRIBE_ONLY - This mode is for users who wish to describe a query prior to execution. Calling OCIStmtExecute() in this mode does not execute the statement, but it does return the select-list description. To maximize performance, it is recommended that applications execute the statement in default mode and use the implicit describe which accompanies the execution.
OCI_EXACT_FETCH - Used when the application knows in advance exactly how many rows it will be fetching. This mode turns prefetching off for Oracle release 8 or later mode, and requires that defines be done before the execute call. Using this mode cancels the cursor after the desired rows are fetched and may result in reduced server-side resource usage.
OCI_PARSE_ONLY - This mode allows the user to parse the query prior to execution. Executing in this mode parses the query and returns parse errors in the SQL, if any. Users must note that this will involve an additional round-trip to the server. To maximize performance, it is recommended that the user execute the statement in the default mode which, as part of a bundled operation, parses the statement.
OCI_STMT_SCROLLABLE_READONLY - Required for the result set to be scrollable. The result set cannot be updated. See "Fetching Results". Cannot be used with any other mode.
The modes are not mutually exclusive and can be used together, except for OCI_STMT_SCROLLABLE_READONLY.Comments
This function is used to execute a prepared SQL statement. Using an execute call, the application associates a request with a server.If a SELECT statement is executed, the description of the select-list is available implicitly as a response. This description is buffered on the client side for describes, fetches and define type conversions. Hence it is optimal to describe a select list only after an execute.See Also:
"Describing Select-List Items"Also for SELECT statements, some results are available implicitly. Rows will be received and buffered at the end of the execute. For queries with small row count, a prefetch causes memory to be released in the server if the end of fetch is reached, an optimization that may result in memory usage reduction. Set attribute call has been defined to set the number of rows to be prefetched for each result set.For SELECT statements, at the end of the execute, the statement handle implicitly maintains a reference to the service context on which it is executed. It is the user's responsibility to maintain the integrity of the service context. The implicit reference is maintained until the statement handle is freed or the fetch is cancelled or an end of fetch condition is reached.Note:
If output variables are defined for a SELECT statement before a call to OCIStmtExecute(), the number of rows specified by iters will be fetched directly into the defined output buffers and additional rows equivalent to the prefetch count will be prefetched. If there are no additional rows, then the fetch is complete without calling OCIStmtFetch().Related Functions
OCIStmtPrepare()

完整正确的测试程序

开新工程时,将合适的OCI库包进工程就能编译过了.

// @file oci_test_on_vs2017.cpp
// @brief test oci interface#include "stdafx.h"
#include <windows.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <string>
#include <conio.h>// OCI开发环境配置
// 远端oracle服务器端装好,配好TNS服务名称
//
// 安装oracle客户端软件时,选第3项(开发工具).
// oracle客户端安装完后,用自带的网络助手配置监听器和远端的TNS服务名称
//
// 将工程设定为win64, 包含进OCI头文件和库文件.
// 在打开远端oracle服务器(进入服务器桌面)的情况下,就可以运行调试测试程序了.
// 不用配ODBS的DSN.#include "oci.h"
// oci.lib is win64, win32编译不过.
// 要安装win32版的oracle client后,拷贝oci开发目录出来用
#pragma comment(lib, "oci.lib")
// #pragma comment(lib, "ociw32.lib")// 用oracle网络助手配置的远端网络服务名称, 不是ODBC助手配置出来的dsn名称
#define REMOTE_TNS_SERVICE_NAME "orcl" // 服务名称不区分大小写// 可以用scott或system用户, 来执行OCI操作
#define DB_USER_NAME "scott"
#define DB_USER_PWD "tiger"#define CMD_QUIT "q"
#define CMD_TEST_SELECT_ALL_BUILD_IN_TABLE "test_select"
#define CMD_TEST_SQL "test_sql"
#define CMD_SQL_SCRIPT "sql_script"const char* psz_ary_sql_script[] = {// -- create db// -- 受影响的行: 1// -- drop database my_db_a;// -- 受影响的行: 1// -- create database my_db_a;// -- 受影响的行: 0// -- use my_db_a;// ora8iclent操作ora11gr2的删除表报错(ORA-24333: zero iteration count), 包没有发出去// 可以执行的sql语句类型// "select * from tbl_a",// "select * from tbl_a where id >= 1 and id <= 3",//// 不能执行的sql语句类型// delete "delete from tbl_a where id > 0",// "insert into tbl_a values (1,'name1','student','test user')",// "update tbl_a set note='6 row change' where id >= 1 and id <= 6",// "select * from tbl_a",// "select * from tbl_a where id >= 1 and id <= 1",// "select * from tbl_a where id >= 1 and id <= 2",// "select * from tbl_a where id >= 1 and id <= 3",// "select * from tbl_a where id >= 1 and id <= 4",// "select * from tbl_a where id >= 1 and id <= 5",// "select * from tbl_a where id >= 1 and id <= 6",// NULL,// -- create table"drop table tbl_a",// -- 受影响的行: 0"create table tbl_a (id int ,name varchar(260))",// -- 受影响的行: 0"alter table tbl_a add type varchar(260)",// -- 受影响的行: 0"alter table tbl_a add note varchar(260)",// -- 受影响的行: 0"delete from tbl_a where id > 0",// -- 受影响的行: 1"insert into tbl_a values (1,'name1','student','test user')",// -- 受影响的行: 1"insert into tbl_a values (2,'name2','student','test user')",// -- 受影响的行: 1"insert into tbl_a values (3,'name3','student','test user')",// -- 受影响的行: 1"insert into tbl_a values (4,'name4','student','test user')",// -- 受影响的行: 1"insert into tbl_a values (5,'name5','student','test user')",// -- 受影响的行: 1"insert into tbl_a values (6,'name6','student','test user')",// -- 受影响的行: 1"update tbl_a set note='1 row change' where id = 1",// -- 受影响的行: 2"update tbl_a set note='2 row change' where id >= 1 and id <= 2",// -- 受影响的行: 3"update tbl_a set note='3 row change' where id >= 1 and id <= 3",// -- 受影响的行: 4"update tbl_a set note='4 row change' where id >= 1 and id <= 4",// -- 受影响的行: 5"update tbl_a set note='5 row change' where id >= 1 and id <= 5",// -- 受影响的行: 6"update tbl_a set note='6 row change' where id >= 1 and id <= 6",// -- 不支持排序的select"select * from tbl_a",// -- 受影响的行: 1"delete from tbl_a where id >= 1 and id <= 1","insert into tbl_a values (1,'name1','student','test user')",// -- 受影响的行: 2"delete from tbl_a where id >= 1 and id <= 2","insert into tbl_a values (1,'name1','student','test user')","insert into tbl_a values (2,'name2','student','test user')",// -- 受影响的行: 3"delete from tbl_a where id >= 1 and id <= 3","insert into tbl_a values (1,'name1','student','test user')","insert into tbl_a values (2,'name2','student','test user')","insert into tbl_a values (3,'name3','student','test user')",// -- 受影响的行: 4"delete from tbl_a where id >= 1 and id <= 4","insert into tbl_a values (1,'name1','student','test user')","insert into tbl_a values (2,'name2','student','test user')","insert into tbl_a values (3,'name3','student','test user')","insert into tbl_a values (4,'name4','student','test user')",// -- 受影响的行: 5"delete from tbl_a where id >= 1 and id <= 5","insert into tbl_a values (1,'name1','student','test user')","insert into tbl_a values (2,'name2','student','test user')","insert into tbl_a values (3,'name3','student','test user')","insert into tbl_a values (4,'name4','student','test user')","insert into tbl_a values (5,'name5','student','test user')",// -- 受影响的行: 6"delete from tbl_a where id >= 1 and id <= 6","insert into tbl_a values (1,'name1','student','test user')","insert into tbl_a values (2,'name2','student','test user')","insert into tbl_a values (3,'name3','student','test user')","insert into tbl_a values (4,'name4','student','test user')","insert into tbl_a values (5,'name5','student','test user')","insert into tbl_a values (6,'name6','student','test user')","commit",NULL
};const char* psz_ary_case_sql[] = {// "select table_name,tablespace_name,temporary from user_tables",// "select 'x' from dual",// "select * from v$version",// "select * from REPCAT$_RESOLUTION_METHOD","select * from AQ$_INTERNET_AGENT_PRIVS",NULL
};const char* psz_ary_orcl_all_tbl_name[] = {"LOGMNR_PARAMETER$","LOGMNR_SESSION$","MVIEW$_ADV_WORKLOAD","MVIEW$_ADV_BASETABLE","MVIEW$_ADV_SQLDEPEND","MVIEW$_ADV_PRETTY","MVIEW$_ADV_TEMP","MVIEW$_ADV_FILTER","MVIEW$_ADV_LOG","MVIEW$_ADV_FILTERINSTANCE","MVIEW$_ADV_LEVEL","MVIEW$_ADV_ROLLUP","MVIEW$_ADV_AJG","MVIEW$_ADV_FJG","MVIEW$_ADV_GC","MVIEW$_ADV_CLIQUE","MVIEW$_ADV_ELIGIBLE","MVIEW$_ADV_OUTPUT","MVIEW$_ADV_EXCEPTIONS","MVIEW$_ADV_PARAMETERS","MVIEW$_ADV_INFO","MVIEW$_ADV_JOURNAL","MVIEW$_ADV_PLAN","AQ$_QUEUE_TABLES","AQ$_QUEUES", // 这个表特别的大"AQ$_SCHEDULES","AQ$_INTERNET_AGENTS","AQ$_INTERNET_AGENT_PRIVS","DEF$_ERROR","DEF$_DESTINATION","DEF$_CALLDEST","DEF$_DEFAULTDEST","DEF$_LOB", // 这个表特别的大"DEF$_PROPAGATOR","DEF$_ORIGIN","DEF$_PUSHED_TRANSACTIONS","REPCAT$_REPCAT","REPCAT$_FLAVORS","REPCAT$_REPSCHEMA","REPCAT$_SNAPGROUP","REPCAT$_REPOBJECT","REPCAT$_REPCOLUMN","REPCAT$_KEY_COLUMNS","REPCAT$_GENERATED","REPCAT$_REPPROP","REPCAT$_REPCATLOG","REPCAT$_DDL","REPCAT$_REPGROUP_PRIVS","REPCAT$_PRIORITY_GROUP","REPCAT$_PRIORITY","REPCAT$_COLUMN_GROUP","REPCAT$_GROUPED_COLUMN","REPCAT$_CONFLICT","REPCAT$_RESOLUTION_METHOD","REPCAT$_RESOLUTION","REPCAT$_RESOLUTION_STATISTICS","REPCAT$_RESOL_STATS_CONTROL","REPCAT$_PARAMETER_COLUMN","REPCAT$_AUDIT_ATTRIBUTE","REPCAT$_AUDIT_COLUMN","REPCAT$_FLAVOR_OBJECTS","REPCAT$_TEMPLATE_STATUS","REPCAT$_TEMPLATE_TYPES","REPCAT$_REFRESH_TEMPLATES","REPCAT$_USER_AUTHORIZATIONS","REPCAT$_OBJECT_TYPES","REPCAT$_TEMPLATE_REFGROUPS","REPCAT$_TEMPLATE_OBJECTS","REPCAT$_TEMPLATE_PARMS","REPCAT$_OBJECT_PARMS","REPCAT$_USER_PARM_VALUES","REPCAT$_TEMPLATE_SITES","REPCAT$_SITE_OBJECTS","REPCAT$_RUNTIME_PARMS","REPCAT$_TEMPLATE_TARGETS","REPCAT$_EXCEPTIONS","REPCAT$_INSTANTIATION_DDL","REPCAT$_EXTENSION","REPCAT$_SITES_NEW","LOGSTDBY$PARAMETERS","LOGSTDBY$EVENTS","LOGSTDBY$APPLY_MILESTONE","LOGSTDBY$SCN","LOGSTDBY$FLASHBACK_SCN","LOGSTDBY$PLSQL","LOGSTDBY$SKIP_TRANSACTION","LOGSTDBY$SKIP","LOGSTDBY$SKIP_SUPPORT","LOGSTDBY$HISTORY","LOGSTDBY$EDS_TABLES","DEF$_AQCALL", // 这个表特别的大"DEF$_AQERROR", // 这个表特别的大"SQLPLUS_PRODUCT_PROFILE","MVIEW$_ADV_INDEX","MVIEW$_ADV_PARTITION","HELP","LOGMNR_GT_TAB_INCLUDE$","LOGMNR_GT_USER_INCLUDE$","LOGMNR_GT_XID_INCLUDE$","LOGMNRT_MDDL$","OL$","OL$HINTS","OL$NODES","LOGMNR_DICTSTATE$","LOGMNRC_GTLO","LOGMNRC_GTCS","LOGMNRC_GSII","LOGMNRC_GSBA","LOGMNR_SEED$","LOGMNR_DICTIONARY$","LOGMNR_OBJ$","LOGMNR_TAB$","LOGMNR_COL$","LOGMNR_ATTRCOL$","LOGMNR_TS$","LOGMNR_IND$","LOGMNR_USER$","LOGMNR_TABPART$","LOGMNR_TABSUBPART$","LOGMNR_TABCOMPART$","LOGMNR_TYPE$","LOGMNR_COLTYPE$","LOGMNR_ATTRIBUTE$","LOGMNR_LOB$","LOGMNR_CDEF$","LOGMNR_CCOL$","LOGMNR_ICOL$","LOGMNR_LOBFRAG$","LOGMNR_INDPART$","LOGMNR_INDSUBPART$","LOGMNR_INDCOMPART$","LOGMNR_LOGMNR_BUILDLOG","LOGMNR_NTAB$","LOGMNR_OPQTYPE$","LOGMNR_SUBCOLTYPE$","LOGMNR_KOPM$","LOGMNR_PROPS$","LOGMNR_ENC$","LOGMNR_REFCON$","LOGMNR_PARTOBJ$","LOGMNRP_CTAS_PART_MAP","LOGSTDBY$APPLY_PROGRESS","MVIEW$_ADV_OWB","LOGMNRC_DBNAME_UID_MAP","LOGMNR_RESTART_CKPT$", // 这个表特别的大"LOGMNR_AGE_SPILL$", // 这个表特别的大"LOGMNR_SESSION_EVOLVE$","LOGMNR_UID$","LOGMNR_SESSION_ACTIONS$","LOGMNR_SPILL$", // 这个表特别的大"LOGMNR_FILTER$","LOGMNR_PROCESSED_LOG$","LOGMNR_GLOBAL$","LOGMNR_RESTART_CKPT_TXINFO$", // 这个表特别的大"LOGMNR_LOG$","LOGMNR_ERROR$",NULL
};typedef struct _tag_col_info{char* m_psz_name;int m_i_len_name;int m_i_data_type_org;int m_i_data_type_now;char* m_psz_data;int m_i_len_data;_tag_col_info() {m_psz_name = NULL;m_i_len_name = 0;m_i_data_type_org = SQLT_CHR;m_i_data_type_now = SQLT_CHR;m_psz_data = NULL;m_i_len_data = 0;}void clear() {if (NULL != m_psz_name) {delete [] m_psz_name;m_psz_name = NULL;}if (NULL != m_psz_data) {delete [] m_psz_data;m_psz_data = NULL;}m_i_len_name = 0;m_i_len_data = 0;m_i_data_type_org = SQLT_CHR;m_i_data_type_now = SQLT_CHR;}
}TAG_COL_INFO;void task_readme();
std::string get_oci_error(const char* psz_tip, OCIError* h_oci_error);
void print_oci_error(const char* psz_tip, OCIError* h_oci_error);
void do_oci_task_ex(OCIEnv* h_oci_env, OCIServer* h_oci_server, OCIError* h_oci_error, OCISvcCtx* h_oci_context, OCISession* h_oci_user);
void do_oci_task(const char* psz_sql, OCIEnv* h_oci_env, OCIServer* h_oci_server, OCIError* h_oci_error, OCISvcCtx* h_oci_context, OCISession* h_oci_user);
void do_oci_task_sql_script(const char* psz_sql, OCIEnv* h_oci_env, OCIServer* h_oci_server, OCIError* h_oci_error, OCISvcCtx* h_oci_context, OCISession* h_oci_user);
void do_oci_task_exec_one_sql(const char* psz_sql, OCIEnv* h_oci_env, OCIServer* h_oci_server, OCIError* h_oci_error, OCISvcCtx* h_oci_context, OCISession* h_oci_user);
void do_oci_task_exec_one_sql_bad(const char* psz_sql, OCIEnv* h_oci_env, OCIServer* h_oci_server, OCIError* h_oci_error, OCISvcCtx* h_oci_context, OCISession* h_oci_user);void case_oci_opt();int g_i_columns_cnt = 0;
TAG_COL_INFO g_col_info[100];int _tmain(int argc, _TCHAR* argv[])
{case_oci_opt();printf("END\n");system("pause");return 0;
}void case_oci_opt()
{sword sw_rc = 0;sword sw_tmp = 0;OCIEnv* h_oci_env = NULL; // 环境句柄OCIServer* h_oci_server = NULL; // 服务器句柄OCIError* h_oci_error = NULL; // 错误句柄OCISvcCtx* h_oci_context = NULL; // 上下文句柄OCISession* h_oci_user = NULL; // 用户句柄sb4 errcode = 0;do {// 打印数据库连接信息printf("connect local tns service name [%s], user name = [%s], password = [%s]\r\n",REMOTE_TNS_SERVICE_NAME,DB_USER_NAME,DB_USER_PWD);// 创建环境句柄(线程和环境对象)sw_rc = OCIEnvCreate(&h_oci_env, OCI_THREADED | OCI_OBJECT, (dvoid*)0, 0, 0, 0, (size_t)0, (dvoid**)0);if (OCI_SUCCESS != sw_rc) {print_oci_error("error : create env handle", h_oci_error);break;}// 创建服务器句柄sw_rc = OCIHandleAlloc((dvoid*)h_oci_env, (dvoid**)&h_oci_server, OCI_HTYPE_SERVER, 0, (dvoid**)0);if (OCI_SUCCESS != sw_rc) {print_oci_error("error : create service handle", h_oci_error);break;}// 创建错误句柄sw_rc = OCIHandleAlloc((dvoid*)h_oci_env, (dvoid**)&h_oci_error, OCI_HTYPE_ERROR, 0, (dvoid**)0);if (OCI_SUCCESS != sw_rc) {print_oci_error("error : create error handle", h_oci_error);break;}// OCI连接的不是ODBC DSN名称// my_oracle_dsn// ORA-12154: TNS: 无法解析指定的连接标识符// OCI连接的是远端TNS服务名称// TNSPING ORCL// 成功// 如果远端的oracle服务器关了,这里会显示错误:连接超时// ORA-12170: TNS: 连接超时// 连接远程数据库(tns服务名称)sw_rc = OCIServerAttach(h_oci_server, h_oci_error,(text*)REMOTE_TNS_SERVICE_NAME,(sb4)strlen(REMOTE_TNS_SERVICE_NAME),OCI_DEFAULT);// packet 1~18if (OCI_SUCCESS != sw_rc) {print_oci_error("error : remote database connect", h_oci_error);break;}// 创建上下文sw_rc = OCIHandleAlloc((dvoid*)h_oci_env, (dvoid**)&h_oci_context, OCI_HTYPE_SVCCTX, 0, (dvoid**)0);// packet 19~20if (OCI_SUCCESS != sw_rc) {print_oci_error("error : create context", h_oci_error);break;}// 设置上下文属性sw_rc = OCIAttrSet((dvoid**)h_oci_context, OCI_HTYPE_SVCCTX, (dvoid*)h_oci_server, (ub4)0, OCI_ATTR_SERVER, h_oci_error);if (OCI_SUCCESS != sw_rc) {print_oci_error("error : set context", h_oci_error);break;}// 创建用户句柄sw_rc = OCIHandleAlloc((dvoid*)h_oci_env, (dvoid**)&h_oci_user, OCI_HTYPE_SESSION, 0, (dvoid**)0);if (OCI_SUCCESS != sw_rc) {print_oci_error("error : create user", h_oci_error);break;}// 设置用户名sw_rc = OCIAttrSet((dvoid*)h_oci_user, OCI_HTYPE_SESSION, (dvoid*)DB_USER_NAME, (ub4)strlen(DB_USER_NAME), OCI_ATTR_USERNAME, h_oci_error);if (OCI_SUCCESS != sw_rc) {print_oci_error("error : set user name", h_oci_error);break;}// 设置口令sw_rc = OCIAttrSet((dvoid*)h_oci_user, OCI_HTYPE_SESSION, (dvoid*)DB_USER_PWD, (ub4)strlen(DB_USER_PWD), OCI_ATTR_PASSWORD, h_oci_error);if (OCI_SUCCESS != sw_rc) {print_oci_error("error : set user password", h_oci_error);break;}// 会话开始sw_rc = OCISessionBegin(h_oci_context, h_oci_error, h_oci_user, OCI_CRED_RDBMS, OCI_DEFAULT);// packet 21~26if (OCI_SUCCESS != sw_rc) {print_oci_error("error : session begin", h_oci_error);break;}// 在会话上设置用户信息sw_rc = OCIAttrSet((dvoid*)h_oci_context, OCI_HTYPE_SVCCTX, (dvoid*)h_oci_user, (ub4)0, OCI_ATTR_SESSION, h_oci_error);if (OCI_SUCCESS != sw_rc) {print_oci_error("error : set user info on service handle", h_oci_error);break;}// 干活do_oci_task_ex(h_oci_env, h_oci_server, h_oci_error, h_oci_context, h_oci_user);printf("ok : db operation over\r\n");} while (0);// 会话结束sw_rc = OCISessionEnd(h_oci_context, h_oci_error, h_oci_user, OCI_DEFAULT);// packet 39~41if (OCI_SUCCESS != sw_rc) {print_oci_error("error : end session", h_oci_error);}// 断开连接sw_rc = OCIServerDetach(h_oci_server, h_oci_error, OCI_DEFAULT);// packet 42`46if (OCI_SUCCESS != sw_rc) {print_oci_error("error : detach server", h_oci_error);}// --------------------------------------------------------------------------------// 释放句柄// --------------------------------------------------------------------------------sw_rc = OCIHandleFree((void*)h_oci_user, OCI_HTYPE_SESSION);if (OCI_SUCCESS != sw_rc) {print_oci_error("error : OCI_HTYPE_SESSION", h_oci_error);}sw_rc = OCIHandleFree((void*)h_oci_context, OCI_HTYPE_SVCCTX);if (OCI_SUCCESS != sw_rc) {print_oci_error("error : OCI_HTYPE_SVCCTX", h_oci_error);}sw_rc = OCIHandleFree((void*)h_oci_error, OCI_HTYPE_ERROR);if (OCI_SUCCESS != sw_rc) {print_oci_error("error : OCI_HTYPE_ERROR", NULL);}sw_rc = OCIHandleFree((void*)h_oci_server, OCI_HTYPE_SERVER);if (OCI_SUCCESS != sw_rc) {print_oci_error("error : OCI_HTYPE_SERVER", NULL);}sw_rc = OCIHandleFree((void*)h_oci_env, OCI_HTYPE_ENV);if (OCI_SUCCESS != sw_rc) {print_oci_error("error : OCI_HTYPE_ENV", NULL);}
}std::string get_oci_error(const char* psz_tip, OCIError* h_oci_error)
{char sz_buf[4096] = { '\0' };sword sw_rc = 0;sb4 errcode = 0;std::string str_rc = "";if (NULL != psz_tip) {str_rc += psz_tip;}str_rc += "\r\n";if (NULL != h_oci_error) {sw_rc = OCIErrorGet(h_oci_error,(ub4)1,(text*)NULL,&errcode,(OraText*)sz_buf,(ub4)sizeof(sz_buf),(b4)OCI_HTYPE_ERROR);if (OCI_SUCCESS == sw_rc) {str_rc += "\t";str_rc += sz_buf;}}return str_rc;
}void print_oci_error(const char* psz_tip, OCIError* h_oci_error)
{printf("%s\r\n", get_oci_error(psz_tip, h_oci_error).c_str());
}void do_oci_task_ex(OCIEnv* h_oci_env, OCIServer* h_oci_server, OCIError* h_oci_error, OCISvcCtx* h_oci_context, OCISession* h_oci_user)
{char sz_sql[4096] = { '\0' };char c_tmp = '\0';int i = 0;do {task_readme();fflush(stdin);memset(sz_sql, 0, sizeof(sz_sql));do {c_tmp = _getch();if ((c_tmp == '\r') || (strlen(sz_sql) >= (sizeof(sz_sql) - 1))) {printf("\n");break;}if ('\b' == c_tmp) {task_readme();fflush(stdin);memset(sz_sql, 0, sizeof(sz_sql));continue;}sz_sql[strlen(sz_sql)] = c_tmp;printf("%c", c_tmp);} while (1);printf("input is : %s\n", sz_sql);if (0 == strcmp(CMD_QUIT, sz_sql)) {printf("user command to quit\n");break;}else if (0 == strcmp(CMD_TEST_SELECT_ALL_BUILD_IN_TABLE, sz_sql)) {for (i = 0; i < sizeof(psz_ary_orcl_all_tbl_name) / sizeof(psz_ary_orcl_all_tbl_name[0]); i++) {if (NULL == psz_ary_orcl_all_tbl_name[i]) {break;}printf("test task [%d] begin ...\n", i);memset(sz_sql, 0, sizeof(sz_sql));sprintf(sz_sql, "select * from %s", psz_ary_orcl_all_tbl_name[i]);printf("execut sql \"%s\" ...\r\n", sz_sql);do_oci_task(sz_sql, h_oci_env, h_oci_server, h_oci_error, h_oci_context, h_oci_user);printf("test task [%d] end ...\n", i);}}else if (0 == strcmp(CMD_TEST_SQL, sz_sql)) {for (i = 0; i < sizeof(psz_ary_case_sql) / sizeof(psz_ary_case_sql[0]); i++) {if (NULL == psz_ary_case_sql[i]) {break;}printf("test task [%d] begin ...\n", i);memset(sz_sql, 0, sizeof(sz_sql));sprintf(sz_sql, "%s", psz_ary_case_sql[i]);printf("execut sql \"%s\" ...\r\n", sz_sql);do_oci_task(sz_sql, h_oci_env, h_oci_server, h_oci_error, h_oci_context, h_oci_user);printf("test task [%d] end ...\n", i);}}else if (0 == strcmp(CMD_SQL_SCRIPT, sz_sql)) {printf("test sql script ...\n");do_oci_task_sql_script(sz_sql, h_oci_env, h_oci_server, h_oci_error, h_oci_context, h_oci_user);printf("test sql script END\n");}else {printf("execut sql \"%s\" ...\r\n", sz_sql);do_oci_task(sz_sql, h_oci_env, h_oci_server, h_oci_error, h_oci_context, h_oci_user);}} while (1);
}void task_readme()
{printf("\n");printf("// --------------------------------------------------------------------------------\n");printf("// 任务列表:\n");printf("// 输入SQL语句, 回车, 执行输入的SQL语句\n");printf("// 输入'" CMD_SQL_SCRIPT "', 执行预置的sql语句数组(sql_script.txt), 只执行SQL, 不进行其他附加操作\n");printf("// 输入'" CMD_TEST_SELECT_ALL_BUILD_IN_TABLE "', 对预置的表名数组进行select * 操作\n");printf("// 输入'" CMD_TEST_SQL "', 执行预置的sql语句数组\n");printf("// 输入'" CMD_QUIT "'退出\n");printf("// --------------------------------------------------------------------------------\n");
}void do_oci_task(const char* psz_sql, OCIEnv* h_oci_env, OCIServer* h_oci_server, OCIError* h_oci_error, OCISvcCtx* h_oci_context, OCISession* h_oci_user)
{OraText* ora_text_select = (OraText*)psz_sql;sword sw_rc = 0;OCIStmt* h_oci_stmt = NULL; // SQL语句句柄OCIDefine* h_oci_define = NULL;OCIParam* h_oci_param = NULL;OraText* colName = NULL;ub4 colNameSize = 0;ub2 stmt_type = 0; // SQL语句类型ub4 fieldCount = 0; // 结果集字段数量ub4 i_index = 0;int i_row_index = 0;ub4 col_len = 0;ub4 col_lenSize = 0;int dtypeNew = 0;ub4 dtype = 0;do {if ((NULL == h_oci_env)|| (NULL == h_oci_server)|| (NULL == h_oci_error)|| (NULL == h_oci_user)|| (NULL == h_oci_context)) {printf("oci handle invalid\r\n");break;}printf("do oci task\r\n");if (NULL != psz_sql) {SetConsoleTitleA(psz_sql);}if (0 == strlen(psz_sql)) {printf("please input sql\n");break;}// 建立SQL语句句柄sw_rc = OCIHandleAlloc(h_oci_env, (void**)&h_oci_stmt, OCI_HTYPE_STMT, (size_t)0, (dvoid**)0);if (OCI_SUCCESS != sw_rc) {print_oci_error("error : create OCI_HTYPE_STMT", h_oci_error);break;}// 准备SQL语句sw_rc = OCIStmtPrepare(h_oci_stmt, h_oci_error, ora_text_select, (ub4)strlen((const char*)ora_text_select), (ub4)OCI_NTV_SYNTAX, (ub4)OCI_DEFAULT);if (OCI_SUCCESS != sw_rc) {print_oci_error("error : OCIStmtPrepare", h_oci_error);break;}// 执行SQLprintf("sw_rc = OCIStmtExecute(h_oci_context, h_oci_stmt, h_oci_error, (ub4)0, (ub4)0, (OCISnapshot*)0, (OCISnapshot*)0, OCI_DEFAULT);\r\n");sw_rc = OCIStmtExecute(h_oci_context, h_oci_stmt, h_oci_error, (ub4)0, (ub4)0, (OCISnapshot*)0, (OCISnapshot*)0, OCI_DEFAULT);// packet 27~29if (OCI_SUCCESS != sw_rc) {print_oci_error("error : OCIStmtExecute", h_oci_error);break;}// printf("press any key to get result set\n");// _getch();// 获取SQL语句类型sw_rc = OCIAttrGet(h_oci_stmt, OCI_HTYPE_STMT, &stmt_type, NULL, OCI_ATTR_STMT_TYPE, h_oci_error);if (OCI_SUCCESS != sw_rc) {print_oci_error("error : OCI_ATTR_STMT_TYPE", h_oci_error);break;}// 取结果集列信息if (OCI_STMT_SELECT == stmt_type) {printf("query result set :\r\n");printf("sw_rc = OCIAttrGet(h_oci_stmt, OCI_HTYPE_STMT, &fieldCount, NULL, OCI_ATTR_PARAM_COUNT, h_oci_error);\r\n");sw_rc = OCIAttrGet(h_oci_stmt, OCI_HTYPE_STMT, &fieldCount, NULL, OCI_ATTR_PARAM_COUNT, h_oci_error);if (OCI_SUCCESS != sw_rc) {print_oci_error("error : OCI_ATTR_STMT_TYPE", h_oci_error);break;}printf("query result set columns = %d\r\n", fieldCount);g_i_columns_cnt = fieldCount;for (i_index = 0; i_index < fieldCount; i_index++) {h_oci_param = NULL;dtype = 0;printf("columns %d : \r\n", i_index + 1);ub4 dtypeSize = sizeof(dtype);sw_rc = OCIParamGet(h_oci_stmt, OCI_HTYPE_STMT, h_oci_error, (void**)&h_oci_param, i_index + 1);if (OCI_SUCCESS != sw_rc){print_oci_error("error : OCIParamGet", h_oci_error);break;}sw_rc = OCIAttrGet(h_oci_param, OCI_DTYPE_PARAM, &dtype, &dtypeSize, OCI_ATTR_DATA_TYPE, h_oci_error);if (OCI_SUCCESS != sw_rc){print_oci_error("error : OCIAttrGet", h_oci_error);break;}g_col_info[i_index].m_i_data_type_org = (int)dtype;printf("\tg_col_info[%d].m_i_data_type_org = %d\r\n", i_index, g_col_info[i_index].m_i_data_type_org);colName = NULL;colNameSize = sizeof(colName);sw_rc = OCIAttrGet(h_oci_param, OCI_DTYPE_PARAM, &colName, &colNameSize, OCI_ATTR_NAME, h_oci_error);if (OCI_SUCCESS != sw_rc){print_oci_error("error : OCIAttrGet", h_oci_error);break;}g_col_info[i_index].m_i_len_name = (int)colNameSize;g_col_info[i_index].m_psz_name = new char[g_col_info[i_index].m_i_len_name + 1];memset(g_col_info[i_index].m_psz_name, 0, g_col_info[i_index].m_i_len_name + 1);// strcpy_s(g_col_info[i_index].m_psz_name, g_col_info[i_index].m_i_len_name, (char*)colName);memcpy(g_col_info[i_index].m_psz_name, (char*)colName, g_col_info[i_index].m_i_len_name);printf("\tname = %s\r\n", (char*)g_col_info[i_index].m_psz_name);printf("\tname len = %d\r\n", (int)g_col_info[i_index].m_i_len_name);col_len = 0;col_lenSize = sizeof(col_len);dtypeNew = SQLT_CHR;switch (dtype){case SQLT_DAT:case SQLT_DATE:case SQLT_TIME:case SQLT_TIME_TZ:case SQLT_TIMESTAMP:case SQLT_TIMESTAMP_TZ:case SQLT_TIMESTAMP_LTZ:{dtypeNew = SQLT_ODT;col_len = sizeof(OCIDate);}break;case SQLT_CLOB:case SQLT_CHR:case SQLT_INT:case SQLT_UIN:case SQLT_NUM:case SQLT_FLT:case SQLT_STR:case SQLT_VNU:case SQLT_LNG:case SQLT_VCS:case SQLT_LVC:case SQLT_AFC:case SQLT_AVC:{sw_rc = OCIAttrGet(h_oci_param, OCI_DTYPE_PARAM, &col_len, &col_lenSize, OCI_ATTR_DATA_SIZE, h_oci_error);if (OCI_SUCCESS != sw_rc){print_oci_error("error : OCIAttrGet", h_oci_error);break;}printf("\tdata len = %d\r\n", (int)col_len);dtypeNew = SQLT_CHR;}break;default:// assert(0);break;}g_col_info[i_index].m_i_data_type_now = (int)dtypeNew;printf("\tg_col_info[%d].m_i_data_type_now = %d\r\n", i_index, g_col_info[i_index].m_i_data_type_now);g_col_info[i_index].m_i_len_data = (int)col_len;g_col_info[i_index].m_psz_data = new char[g_col_info[i_index].m_i_len_data + 1];memset(g_col_info[i_index].m_psz_data, 0, g_col_info[i_index].m_i_len_data + 1);h_oci_define = NULL;sw_rc = OCIDefineByPos(h_oci_stmt, &h_oci_define, h_oci_error, i_index + 1, g_col_info[i_index].m_psz_data, col_len * sizeof(char), dtypeNew, 0, 0, 0, OCI_DEFAULT);if (OCI_SUCCESS != sw_rc){print_oci_error("error : OCIDefineByPos", h_oci_error);break;}printf("----------------------------------------\r\n");}}// 遍历行集i_row_index = 0;do {sw_rc = OCIStmtFetch(h_oci_stmt, h_oci_error, 1, OCI_FETCH_NEXT, OCI_DEFAULT);// 如果是查第一行,并不发收包,可能执行后,返回的数据中已经包含第一行// packet 30~32 如果数据不够了,会继续请求包。// packet 33~35// packet 36~38if (OCI_NO_DATA == sw_rc){// 只有OCI_NO_DATA代表行集读完了printf("OCI_NO_DATA\n");break;}if (OCI_SUCCESS != sw_rc){printf("error : sw_rc = %d\n", sw_rc);// sw_rc is -1print_oci_error("OCIStmtFetch", h_oci_error);// ORA-01405: 提取的列值为 NULL// 只是这行有问题, 可以继续读下一行// 看了表内容, 确实有的字段是NULLcontinue;}for (i_index = 0; i_index != g_i_columns_cnt; i_index++){printf("row[%d]col[%d] = %s\r\n", i_row_index, i_index, (NULL != g_col_info[i_index].m_psz_data) ? g_col_info[i_index].m_psz_data : "NULL");}printf("----------------------------------------\r\n");i_row_index++;// break; // @todo for debug, only show one row} while (1);// 释放资源for (i_index = 0; i_index != g_i_columns_cnt; i_index++){g_col_info[i_index].clear();}} while (0);printf("press any key to end the query\n");_getch();printf("will be end query\n");Sleep(1000);// 释放oci句柄if (NULL != h_oci_stmt) {sw_rc = OCIHandleFree((void*)h_oci_stmt, OCI_HTYPE_STMT);}if (OCI_SUCCESS != sw_rc) {print_oci_error("error : OCI_HTYPE_STMT", NULL);}
}void do_oci_task_sql_script(const char* psz_sql, OCIEnv* h_oci_env, OCIServer* h_oci_server, OCIError* h_oci_error, OCISvcCtx* h_oci_context, OCISession* h_oci_user)
{int i = 0;char sz_sql[4096] = {'\0'};for (i = 0; i < sizeof(psz_ary_sql_script) / sizeof(psz_ary_sql_script[0]); i++) {if (NULL == psz_ary_sql_script[i]) {break;}memset(sz_sql, 0, sizeof(sz_sql));sprintf(sz_sql, "%s", psz_ary_sql_script[i]);printf("test sql_script [%d] : execut sql \"%s\" ...\r\n", i, sz_sql);do_oci_task_exec_one_sql(sz_sql, h_oci_env, h_oci_server, h_oci_error, h_oci_context, h_oci_user);}
}void do_oci_task_exec_one_sql_bad(const char* psz_sql, OCIEnv* h_oci_env, OCIServer* h_oci_server, OCIError* h_oci_error, OCISvcCtx* h_oci_context, OCISession* h_oci_user)
{OraText* ora_text_select = (OraText*)psz_sql;sword sw_rc = 0;OCIStmt* h_oci_stmt = NULL; // SQL语句句柄OCIDefine* h_oci_define = NULL;OCIParam* h_oci_param = NULL;OraText* colName = NULL;ub4 colNameSize = 0;ub2 stmt_type = 0; // SQL语句类型ub4 fieldCount = 0; // 结果集字段数量ub4 i_index = 0;int i_row_index = 0;ub4 col_len = 0;ub4 col_lenSize = 0;int dtypeNew = 0;ub4 dtype = 0;do {if ((NULL == h_oci_env)|| (NULL == h_oci_server)|| (NULL == h_oci_error)|| (NULL == h_oci_user)|| (NULL == h_oci_context)) {printf("oci handle invalid\r\n");break;}printf("do oci task\r\n");if (NULL != psz_sql) {SetConsoleTitleA(psz_sql);}if (0 == strlen(psz_sql)) {printf("please input sql\n");break;}// 建立SQL语句句柄sw_rc = OCIHandleAlloc(h_oci_env, (void**)&h_oci_stmt, OCI_HTYPE_STMT, (size_t)0, (dvoid**)0);if (OCI_SUCCESS != sw_rc) {print_oci_error("error : create OCI_HTYPE_STMT", h_oci_error);break;}// 准备SQL语句sw_rc = OCIStmtPrepare(h_oci_stmt, h_oci_error, ora_text_select, (ub4)strlen((const char*)ora_text_select), (ub4)OCI_NTV_SYNTAX, (ub4)OCI_DEFAULT);if (OCI_SUCCESS != sw_rc) {print_oci_error("error : OCIStmtPrepare", h_oci_error);break;}// 执行SQLprintf("sw_rc = OCIStmtExecute(h_oci_context, h_oci_stmt, h_oci_error, (ub4)0, (ub4)0, (OCISnapshot*)0, (OCISnapshot*)0, OCI_DEFAULT);\r\n");sw_rc = OCIStmtExecute(h_oci_context, h_oci_stmt, h_oci_error, (ub4)0, (ub4)0, (OCISnapshot*)0, (OCISnapshot*)0, OCI_DEFAULT);// packet 27~29if (OCI_SUCCESS != sw_rc) {print_oci_error("error : OCIStmtExecute", h_oci_error);break;}} while (0);// 释放oci句柄if (NULL != h_oci_stmt) {sw_rc = OCIHandleFree((void*)h_oci_stmt, OCI_HTYPE_STMT);}if (OCI_SUCCESS != sw_rc) {print_oci_error("error : OCI_HTYPE_STMT", NULL);}
}void do_oci_task_exec_one_sql(const char* psz_sql, OCIEnv* h_oci_env, OCIServer* h_oci_server, OCIError* h_oci_error, OCISvcCtx* h_oci_context, OCISession* h_oci_user)
{OraText* ora_text_select = (OraText*)psz_sql;sword sw_rc = 0;OCIStmt* h_oci_stmt = NULL; // SQL语句句柄OCIDefine* h_oci_define = NULL;OCIParam* h_oci_param = NULL;OraText* colName = NULL;ub4 colNameSize = 0;ub2 stmt_type = OCI_STMT_SELECT; // SQL语句类型ub4 fieldCount = 0; // 结果集字段数量ub4 i_index = 0;int i_row_index = 0;ub4 col_len = 0;ub4 col_lenSize = 0;int dtypeNew = 0;ub4 dtype = 0;do {if ((NULL == h_oci_env)|| (NULL == h_oci_server)|| (NULL == h_oci_error)|| (NULL == h_oci_user)|| (NULL == h_oci_context)) {printf("oci handle invalid\r\n");break;}printf("do_oci_task_exec_one_sql\r\n");if (NULL != psz_sql) {SetConsoleTitleA(psz_sql);}if (0 == strlen(psz_sql)) {printf("please input sql\n");break;}// 建立SQL语句句柄sw_rc = OCIHandleAlloc(h_oci_env, (void**)&h_oci_stmt, OCI_HTYPE_STMT, (size_t)0, (dvoid**)0);if (OCI_SUCCESS != sw_rc) {print_oci_error("error : create OCI_HTYPE_STMT", h_oci_error);break;}// 准备SQL语句sw_rc = OCIStmtPrepare(h_oci_stmt, h_oci_error, ora_text_select, (ub4)strlen((const char*)ora_text_select), (ub4)OCI_NTV_SYNTAX, (ub4)OCI_DEFAULT);if (OCI_SUCCESS != sw_rc) {// ora10通过sid连接ora8.1, 执行除了select语句之外的SQL, 都会得到下列错误// ORA-24333: 零迭代计数print_oci_error("error : OCIStmtPrepare", h_oci_error);break;}// 必须在执行SQL语句前, 获取SQL语句类型用于处理参数4, 防止出现错误 : ORA-24333: zero iteration countsw_rc = OCIAttrGet(h_oci_stmt, OCI_HTYPE_STMT, &stmt_type, NULL, OCI_ATTR_STMT_TYPE, h_oci_error);if (OCI_SUCCESS != sw_rc) {print_oci_error("error : OCI_ATTR_STMT_TYPE", h_oci_error);break;}// 执行SQLprintf("sw_rc = OCIStmtExecute(h_oci_context, h_oci_stmt, h_oci_error, (ub4)0, (ub4)0, (OCISnapshot*)0, (OCISnapshot*)0, OCI_DEFAULT);\r\n");// 处理参数4, 防止报错; ORA-24333sw_rc = OCIStmtExecute(h_oci_context, h_oci_stmt, h_oci_error, (ub4)(OCI_STMT_SELECT == stmt_type ? 0 : 1), (ub4)0, (OCISnapshot*)0, (OCISnapshot*)0,OCI_DEFAULT);// packet 27~29if (OCI_SUCCESS != sw_rc) {print_oci_error("error : OCIStmtExecute", h_oci_error);break;}// printf("press any key to get result set\n");// _getch();// 取结果集列信息if (OCI_STMT_SELECT == stmt_type) {sw_rc = OCIAttrGet(h_oci_stmt, OCI_HTYPE_STMT, &fieldCount, NULL, OCI_ATTR_PARAM_COUNT, h_oci_error);if (OCI_SUCCESS != sw_rc) {print_oci_error("error : OCI_ATTR_STMT_TYPE", h_oci_error);break;}g_i_columns_cnt = fieldCount;for (i_index = 0; i_index < fieldCount; i_index++) {h_oci_param = NULL;dtype = 0;ub4 dtypeSize = sizeof(dtype);sw_rc = OCIParamGet(h_oci_stmt, OCI_HTYPE_STMT, h_oci_error, (void**)&h_oci_param, i_index + 1);if (OCI_SUCCESS != sw_rc){print_oci_error("error : OCIParamGet", h_oci_error);break;}sw_rc = OCIAttrGet(h_oci_param, OCI_DTYPE_PARAM, &dtype, &dtypeSize, OCI_ATTR_DATA_TYPE, h_oci_error);if (OCI_SUCCESS != sw_rc){print_oci_error("error : OCIAttrGet", h_oci_error);break;}g_col_info[i_index].m_i_data_type_org = (int)dtype;colName = NULL;colNameSize = sizeof(colName);sw_rc = OCIAttrGet(h_oci_param, OCI_DTYPE_PARAM, &colName, &colNameSize, OCI_ATTR_NAME, h_oci_error);if (OCI_SUCCESS != sw_rc){print_oci_error("error : OCIAttrGet", h_oci_error);break;}g_col_info[i_index].m_i_len_name = (int)colNameSize;g_col_info[i_index].m_psz_name = new char[g_col_info[i_index].m_i_len_name + 1];memset(g_col_info[i_index].m_psz_name, 0, g_col_info[i_index].m_i_len_name + 1);// strcpy_s(g_col_info[i_index].m_psz_name, g_col_info[i_index].m_i_len_name, (char*)colName);memcpy(g_col_info[i_index].m_psz_name, (char*)colName, g_col_info[i_index].m_i_len_name);col_len = 0;col_lenSize = sizeof(col_len);dtypeNew = SQLT_CHR;switch (dtype){case SQLT_DAT:case SQLT_DATE:case SQLT_TIME:case SQLT_TIME_TZ:case SQLT_TIMESTAMP:case SQLT_TIMESTAMP_TZ:case SQLT_TIMESTAMP_LTZ:{dtypeNew = SQLT_ODT;col_len = sizeof(OCIDate);}break;case SQLT_CLOB:case SQLT_CHR:case SQLT_INT:case SQLT_UIN:case SQLT_NUM:case SQLT_FLT:case SQLT_STR:case SQLT_VNU:case SQLT_LNG:case SQLT_VCS:case SQLT_LVC:case SQLT_AFC:case SQLT_AVC:{sw_rc = OCIAttrGet(h_oci_param, OCI_DTYPE_PARAM, &col_len, &col_lenSize, OCI_ATTR_DATA_SIZE, h_oci_error);if (OCI_SUCCESS != sw_rc){print_oci_error("error : OCIAttrGet", h_oci_error);break;}dtypeNew = SQLT_CHR;}break;default:// assert(0);break;}g_col_info[i_index].m_i_data_type_now = (int)dtypeNew;g_col_info[i_index].m_i_len_data = (int)col_len;g_col_info[i_index].m_psz_data = new char[g_col_info[i_index].m_i_len_data + 1];memset(g_col_info[i_index].m_psz_data, 0, g_col_info[i_index].m_i_len_data + 1);h_oci_define = NULL;sw_rc = OCIDefineByPos(h_oci_stmt, &h_oci_define, h_oci_error, i_index + 1, g_col_info[i_index].m_psz_data, col_len * sizeof(char), dtypeNew, 0, 0, 0, OCI_DEFAULT);if (OCI_SUCCESS != sw_rc){print_oci_error("error : OCIDefineByPos", h_oci_error);break;}}}// 遍历行集i_row_index = 0;do {if (OCI_STMT_SELECT != stmt_type) {// 只有select语句有行集可以遍历break;}sw_rc = OCIStmtFetch(h_oci_stmt, h_oci_error, 1, OCI_FETCH_NEXT, OCI_DEFAULT);// 如果是查第一行,并不发收包,可能执行后,返回的数据中已经包含第一行// packet 30~32 如果数据不够了,会继续请求包。// packet 33~35// packet 36~38if (OCI_NO_DATA == sw_rc){// 只有OCI_NO_DATA代表行集读完了break;}if (OCI_SUCCESS != sw_rc){printf("error : sw_rc = %d\n", sw_rc);// sw_rc is -1print_oci_error("OCIStmtFetch", h_oci_error);// ORA-01405: 提取的列值为 NULL// 只是这行有问题, 可以继续读下一行// 看了表内容, 确实有的字段是NULLcontinue;}for (i_index = 0; i_index != g_i_columns_cnt; i_index++){// printf("row[%d]col[%d] = %s\r\n", i_row_index, i_index, (NULL != g_col_info[i_index].m_psz_data) ? g_col_info[i_index].m_psz_data : "NULL");}// printf("----------------------------------------\r\n");i_row_index++;// break; // @todo for debug, only show one row} while (1);// 释放资源for (i_index = 0; i_index != g_i_columns_cnt; i_index++){g_col_info[i_index].clear();}} while (0);// 释放oci句柄if (NULL != h_oci_stmt) {sw_rc = OCIHandleFree((void*)h_oci_stmt, OCI_HTYPE_STMT);}if (OCI_SUCCESS != sw_rc) {print_oci_error("error : OCI_HTYPE_STMT", NULL);}
}

OCI : ORA-24333: zero iteration count相关推荐

  1. TVMNN编译Compiler栈

    TVMNN编译Compiler栈 内容纲要 前言 调研目标 TVM介绍 TVM源码架构 i. FrontEnd ii. Relay iii. BackEnd VTA实现原理及设计思想提炼 i. 整体结 ...

  2. 【Unity 3D】学习笔记三十六:物理引擎——刚体

    物理引擎就是游戏中模拟真是的物理效果.如两个物体发生碰撞,物体自由落体等.在unity中使用的是NVIDIA的physX,它渲染的游戏画面很逼真. 刚体 刚体是一个很很中要的组件. 默认情况下,新创的 ...

  3. 【Boost】timer、progress_timer和progress_display

    Table of Contents 1 timer 2 progress_timer 3 progress_display 1 timer timer t; //声明一个timer类对象t,调用构造函 ...

  4. arm neon RGB转Gray的例子

    确认处理器是否支持NEON cat /proc/cpuinfo | grep neon 看是否有如下内容 Features : swp half thumb fastmult vfp edsp neo ...

  5. ARM NEON 优化

    确认处理器是否支持NEON cat /proc/cpuinfo | grep neon 看是否有如下内容 Features : swp half thumb fastmult vfp edsp neo ...

  6. MICROSOFT EXCEL FILE FORMAT(BIFF2.1)

    转自:http://www.xgdown.com/article/243/61822_1.htm 作用:http://unruledboy.cnblogs.com/archive/2004/07/07 ...

  7. java 矩阵计算 加减乘除 反转 分解

    矩阵计算 package Jama;import java.text.NumberFormat; import java.text.DecimalFormat; import java.text.De ...

  8. java挖矿算法_Scrypt 不止是加密算法,也是莱特币的挖矿算法

    在密码学中,scrypt(念作"ess crypt")是Colin Percival于2009年所发明的金钥推衍函数,当初设计用在他所创立的Tarsnap服务上.设计时考虑到大规模 ...

  9. 机器学习知识点(十九)矩阵特征值分解基础知识及Java实现

    1.特征值分解基础知识 矩阵乘法Y=AB的数学意义在于变换,以其中一个向量A为中心,则B的作用主要是使A发生伸缩或旋转变换.一个矩阵其实就是一个线性变换,因为一个矩阵乘以一个向量后得到的向量,其实就相 ...

最新文章

  1. PHP编译为静态库,Linux下将Tinyxml编译为静态库
  2. SMTP身份验证(LOGIN、PLAIN、CRAM-MD5)
  3. 在 k8s 中使用 Kubevirt 运行管理 Windows 10 操作系统
  4. 英特尔凌动处理器_曾押宝英特尔凌动CPU,华硕手机如今活得如何了?
  5. 互联网分布式架构技术概述
  6. 简单工程验收单表格_中铁超大型工程项目-123个精细化管理手册配套表格附件,超全...
  7. Liunx安装gogs,mysql,jdk,tomcat等常用软件
  8. Ngs File Type Transfer
  9. mysql数据库插入datetime_往MySQL数据库datetime类型字段中插入数据库的当前时间
  10. in function ‘int main()’_FIND_IN_SET 及IN 处理逗号间隔的字符串参数
  11. 纸片人活了!海报上的梅西、漫画里的悟空,都被AI唤醒
  12. SpringBoot系列六:SpringBoot整合Tomcat
  13. 适用于 Windows PowerShell 的 SMS Cmdlet
  14. linux 查看 shell进程,Linux之shell 和进程
  15. 聊聊V8引擎的垃圾回收
  16. Linux内核编程11期:设备树(device tree)
  17. 字符串拼接的sql注入实战
  18. Java中this的用法总结
  19. 基于KDJ指标的Dual Thrust策略
  20. android退出中国,曾经的安卓机皇宣布关闭中国社区,彻底放弃手机业务了?

热门文章

  1. 广告联盟是什么,其优势有哪些?
  2. 基于过程的软件测试全景图 (2)
  3. redis 内存分析工具 `rma4go`
  4. 一文带你理解前后端分离本质
  5. fatal: unable to access ‘https://github.com/PX4/PX4-Autopilot.git/‘: Failed to connect to github.com
  6. 计算机机房雷电接地,机房防雷接地系统解决方案
  7. 第一章 日常生活中的正念
  8. Re6:读论文 LeSICiN: A Heterogeneous Graph-based Approach for Automatic Legal Statute Identification fro
  9. 互联网征信中的信用评分模型(转)
  10. 中兴通讯智能手机生产链探秘