ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

OCI : ORA-01405: 提取的列值为 NULL

2019-04-22 10:48:31  阅读:297  来源: 互联网

标签:OCI oci error sw LOGMNR 01405 rc NULL


前言

4个月以前,预研了tns314的包分析。当时写了一个OCI测试程序,用来配合抓包。
现在将运行环境搞掉了,重新安装客户端后,发生了2个问题。

  • 装32bits的oraclient, 编译的是64bits的OCI测试程序,引起报错。
    解决方法:将测试工程种加入32bits和64bits的OCI库,根据安装的oraclient的不同(32bits/64bits), 也编译成(32bits/64bits)进行测试。

  • 遍历行集时,出现报错: ORA-01405: 提取的列值为 NULL, 导致测试程序无法遍历结果集。
    解决方法:遍历行集时,如果错误码不是OCI_NO_DATA,说明行集没遍历完,可以继续遍历下一行。只是这一行有NULL内容的字段(用sqldeveloper.exe看了对应的表,确实有NULL内容的字段).

    花时间做过的实验,隔的时间长了,再回头来弄,都忘的差不多了。
    如果及时做笔记,完善保存测试工程。捡起来要方便些。
    特别是自己有多个版本的测试工程时,时间长了,还真要花时间确认一下,才能知道哪个工程才是自己最后完善的那个测试工程。

OCI测试工程下载点

oci_test_on_MP.7z

测试工程预览

// @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" // 服务名称不区分大小写
#define DB_USER_NAME "system"
#define DB_USER_PWD "system"

#define CMD_QUIT "q"
#define CMD_TEST_SELECT_ALL_BUILD_IN_TABLE "test_select"
#define CMD_TEST_SQL "test_sql"

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 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~18

		if (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~20
		if (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~26
		if (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~41
	if (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`46
	if (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 {
			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_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;
		}

		// 执行SQL
		printf("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~29
		if (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~38

			if (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 -1
				print_oci_error("OCIStmtFetch", h_oci_error);
				// ORA-01405: 提取的列值为 NULL

				// 只是这行有问题, 可以继续读下一行
				// 看了表内容, 确实有的字段是NULL
				continue;
			}

			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);
	}
}

标签:OCI,oci,error,sw,LOGMNR,01405,rc,NULL
来源: https://blog.csdn.net/LostSpeed/article/details/79992384

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有