多列转为一列的SQL语句查询并对获取数据解析

教程发布:风哥 教程分类:ITPUX技术网 更新日期:2022-02-12 浏览学习:457

项目开发中,需要从数据库查询数据,在不使用数据库库函数的情况下对获取的数据解析,
这时就可以对查询的SQL语句操作,使其要查询的每一项通过连接符连接在一起成为一项查询,
这时通过查询获取的数据就是一列的数据--一个字符串,再对字符串操作获取对应的每一项数据。
在编程实现中,可以把对SQL语句的操作看着是对字符串的操作,获取的结果也是看做字符串解析。
下面是简单实现,
环境:linux,oracle数据库,OCILIB库

[mw_shl_code=c,true]代码实现:

/*存放每一行数据的结构体*/
typedef struct _resultdata
{
int num;
int row_len;
SB1 *row_data;
struct _resultdata *next;
}ResultData;

/***********************************************************
*function:rs_link_insert
*description:
* 查询数据链表插入,将新的查询数据放进链表中
*input: head:链表头
* pi: 将要插进的新结点
*
*output: ResultData * :返回ResultData *指针,一般是链表
*头结点
* ********************************************************/
ResultData *rs_link_insert(ResultData *head,ResultData *pi)
{
ResultData *pb = NULL;

pb = head;
//链表为空时,创建链表
if(NULL == pb)
{
pb = pi;
pi->next = NULL;
head = pb;

//rs_tail = pi;
return head;
}
//不为空时,找到尾结点,并判断是否为空,为空将新结点
//插入当前尾结点后
//然后将新节点作为尾结点
while(pb->next)
{
//pf = pb;
pb = pb->next;
}
pb->next = pi;
pi->next = NULL;
return head;

}

/***********************************
*function: sql_format_deal
*description:
* 将源字符串中’,‘替换为“||chr(1)||”
*input: source:源字符串
* search:格式化后的字符串
*
*output: 列值
* ********************************/
int sql_format_deal(char* csource_ext,char *cresult)
{
int iwork_bgn = 0;//单词标示
int ibracket = 0;//括号标志
int icol_cnt = 1;//列值
char *csource = (char *)malloc(strlen(csource_ext) + 64);
char *csrc = csource;
char *cres = cresult;

strcpy(csource, csource_ext);
for(iwork_bgn=1,ibracket=0;*csrc;csrc++)
{
//如果到了from处,则不再替换
if((!strncasecmp(csrc,"from",4))&&iwork_bgn)
{
if(csrc[4]==0 || strchr(" \t\r\n",csrc[4]))
{
break;
}
}

//将csrc中‘,’替换为“||chr(1)||”,注:括号内不处理
if(!ibracket && *csrc == ',')
{
// 一个逗号则替换为||chr(1)||,两个逗号作为一个逗号(说明要单作为1列处理)
if(csrc[1]==',')
{
// 保存当前逗号,跳过pi[1]的逗号
*cres++ = *csrc++;
icol_cnt++;
}
else
{
//strcpy(cres,"||chr(1)||");
strcpy(cres,"||chr(1)||");
cres += strlen(cres);//是"||chr(1)||"的长度
}
}
else
{
*cres++ = *csrc;

// 判断是否一个词的开始
iwork_bgn = strchr(" \t\r\n",*csrc)?1:0;
// 判断是否在括号内
if('(' == *csrc)
{
ibracket++;

}
if(')' == *csrc)
{
ibracket--;
}
}

}
// from后面的内容全部拷贝
for(;*csrc;csrc++)
{
*cres++ = *csrc;
}

*cres = '\0';

free(csource);
return icol_cnt;
}
/***********************************
*function: db_select_data
*description:
* 查询SQL语句,获得查询数据,将数据存放在rs_data内
*
*
*input: CN:数据路连接对象
* SQL:SQL执行语句
* *row_num:查询数据行数
* rs_data:存放查询后的数据`
*
*output: >=0:sucess <0:fail *注意:开辟了rs_data及rs_link链表内存空间 * 同时释放了sele_data及se_link链表内存空间 * rs_data及rs_link内存空间由函数 * db_get_le_data释放 * * 开辟了format_sql空间,并在用完后释放 * ********************************/ int db_select_data(OCI_Connection *cn, char* sql,int *row_num,ResultData **rs_data) { OCI_Statement *st = NULL; OCI_Resultset *rs = NULL; int icolmn_cnt = 0; int icnt = 0; ResultData *pb_data = NULL; ResultData *rs_head = NULL; ResultData *rs_node = NULL; int isql_len = 0; SB1 *format_sql = NULL; SB1 *ptemp = NULL; SB1 *p1temp = NULL; SB1 buf_data[MAX_ROW_LENGTH]; SB1 *pbuf_data = NULL; int itemp1 = 0; //char *ptmp = 0; //对SQL语句断言 assert(sql); //判断数据库连接对象是否为空 if(NULL == cn) { zlog_error(fzs_lib_mod_log,"---no connect to oracle,please check connect"); return -1; } pthread_mutex_lock(&mutex_cn); //zlog_error(fzs_lib_mod_log,"cn addr:%p",cn); //通过数据库连接对象获得SQL语句执行对象 st = OCI_StatementCreate(cn); if(NULL == st) { //printf("file:%s---line:%d---OCI_StatementCreate---fail\r\n",POS_INFO); zlog_error(fzs_lib_mod_log,"---OCI_StatementCreate---fail"); OCI_err_handler(OCI_GetLastError()); pthread_mutex_unlock(&mutex_cn); return -1; } //sql格式化后的结构 isql_len = strlen(sql)+1024; //分配内存空间 format_sql = (SB1*)malloc(isql_len); memset(format_sql,0,isql_len); //格式化SQL语句 icolmn_cnt = sql_format_deal(sql,format_sql);//多列的话目前没有处理 //printf("file:%s---line:%d-format_sql=%s\r\n",POS_INFO,format_sql); zlog_debug(fzs_lib_mod_log,"-format_sql=%s",format_sql); //printf("file:%s---line:%d-icolmn_cnt=%d\r\n",POS_INFO,icolmn_cnt); zlog_debug(fzs_lib_mod_log,"-icolmn_cnt=%d",icolmn_cnt); //执行SQL语句 if(!OCI_ExecuteStmt(st,format_sql))// format_sql 是格式化后的语句 { zlog_error(fzs_lib_mod_log,"-OCI_ExecuteStmt---fail"); OCI_err_handler(OCI_GetLastError()); pthread_mutex_unlock(&mutex_cn); return -1; } //获取结果集对象 zlog_debug(fzs_lib_mod_log,"-OCI_ExecuteStmt---OK!!!"); rs = OCI_GetResultset(st); if(NULL == rs) { zlog_error(fzs_lib_mod_log,"OCI_ExecuteStmt---fail"); OCI_err_handler(OCI_GetLastError()); pthread_mutex_unlock(&mutex_cn); return -1; } //对rs结果集中的数据处理,将rs数据存到rs_link中,并获得每行数据长度 while(OCI_FetchNext(rs)) { icnt++; //每次获得数据前,清空buf内数据 //printf("%s\n",OCI_GetString(rs,1)); memset(buf_data,0,MAX_ROW_LENGTH); pbuf_data = buf_data; for(itemp1 = 0; itemp1 < icolmn_cnt; itemp1++) { pbuf_data += strlen(pbuf_data); if(itemp1 > 0)
*pbuf_data++ = 0x01;

sprintf(pbuf_data, OCI_GetString(rs, itemp1 + 1));
}

//printf("file:%s--line:%d--buf_data=%s\r\n",POS_INFO,buf_data);
zlog_debug(fzs_lib_mod_log,"--buf_data=%s",buf_data);
//irow_len = strlen(buf_data)+1;
//printf("file:%s--line:%d--*len=%d\r\n",POS_INFO,*len);
//zlog_debug(fzs_lib_mod_log,"*len=%d",*len);
//给pb_data分配内存空间
pb_data = (ResultData*)malloc(sizeof(ResultData));

//分配内存失败
if(pb_data == NULL)
{

//printf("SelectData--pb_data malloc memory fail\r\n");
zlog_error(fzs_lib_mod_log,"OCI_ExecuteStmt---fail");
//释放返回集
if(rs)
{
OCI_ReleaseResultsets(st);
//printf("file:%s--line:%d--OCI_ReleaseResultsets(st) success\r\n",POS_INFO);
}

//清除声明
if(st)
{
OCI_StatementFree(st);
//printf("file:%s--line:%d--OCI_StatementFree(st) success\r\n",POS_INFO);
}

pthread_mutex_unlock(&mutex_cn);
return -1;
}

pb_data->row_data = (SB1*)malloc((strlen(buf_data)+1));

//分配内存失败
if(pb_data->row_data == NULL)
{
//printf("SelectData--pb_data->row_data malloc memory fail\r\n");
zlog_error(fzs_lib_mod_log,"SelectData--pb_data->row_data malloc memory fail");
free(pb_data);
//释放返回集
if(rs)
{
OCI_ReleaseResultsets(st);
//printf("file:%s--line:%d--OCI_ReleaseResultsets(st) success\r\n",POS_INFO);
}

//清除声明
if(st)
{
OCI_StatementFree(st);
//printf("file:%s--line:%d--OCI_StatementFree(st) success\r\n",POS_INFO);
}

pthread_mutex_unlock(&mutex_cn);
return -1;
}

pb_data->num = icnt;
pb_data->row_len = strlen(buf_data)+1;
//数据全部Copy过来,不是地址赋值过来
memcpy(pb_data->row_data,buf_data,strlen(buf_data)+1);//sizeof(rs)==4,forever
pb_data->row_data[strlen(buf_data)] = '\0';
//将每一行数据作为一个结点存放在链表中
//printf("file:%s--line:%d--pb_data->row_data=%s\r\n",POS_INFO,pb_data->row_data);
zlog_debug(fzs_lib_mod_log,"--pb_data->row_data=%s",pb_data->row_data);
rs_head = rs_link_insert(rs_head,pb_data);
}

//总行数
*row_num = icnt;

*rs_data = rs_head;
//将rs_head指向空指针
rs_head = NULL;

//rs_link_print(*rs_data);

//将每行数据内的0x1替换为0x0
for(rs_node=*rs_data;rs_node;rs_node=rs_node->next)
{
for(ptemp = rs_node->row_data,p1temp = ptemp+rs_node->row_len;ptemp < p1temp;ptemp++) { if(1 == *ptemp) { // printf("file:%s--line:%d--p=%c\r\n",POS_INFO,*p); // zlog_debug(fzs_lib_mod_log,"--p=%c",*p); *ptemp = 0; // printf("file:%s--line:%d--p=%c\r\n",POS_INFO,*p); // zlog_debug(fzs_lib_mod_log,"--p=%c",*p); } } //printf("file:%s--line:%d--rs_node->row_data=%s\r\n",POS_INFO,rs_node->row_data);
zlog_debug(fzs_lib_mod_log,"--rs_node->row_data=%s",rs_node->row_data);
}

//rs_link_print(*rs_data);
//释放format_sql内存空间
free(format_sql);

//释放返回集
if(rs)
{
OCI_ReleaseResultsets(st);
//printf("file:%s--line:%d--OCI_ReleaseResultsets(st) success\r\n",POS_INFO);
}
//清除声明
if(st)
{
OCI_StatementFree(st);
//printf("file:%s--line:%d--OCI_StatementFree(st) success\r\n",POS_INFO);
}

#ifdef SWITCH_LOG
if(1 == db_en_chs_flag)
{
zlog_info(fzs_lib_mod_log,"当前数据库查询花费时间%lu us",(end1_temp-st1_temp));
}
else
{
zlog_info(fzs_lib_mod_log,"The current database query cost time:%lu us",(end1_temp-st1_temp));
}
#endif

pthread_mutex_unlock(&mutex_cn);
return 0;

}

本代码实现中,没有实现主函数,实现了具体处理SQL语句及对获取的数据处理(没有解析出针对每一列),是作为通用函数处理的。[/mw_shl_code]

总结:
1,在对oracle数据库开发中,使用oracle公司开发的OCILIB库开发,相比oci更简单,具体OCILIB库的好处和实现demo请查阅OCILIB库说明;
2,在不使用OCILIB库函数解析从数据库获取的数据时,可以把SQL语句当着字符串处理,通过连接符使多列转为一列SQL语句,这样查询获取的数据也是一列;
3,对OCILIB库函数也要使用得当,掌握基本使用函数和使用技巧。

本文标签:
网站声明:本文由风哥整理发布,转载请保留此段声明,本站所有内容将不对其使用后果做任何承诺,请读者谨慎使用!
【上一篇】
【下一篇】