db2定长import API问题解决,与大家分享!!
2006-09-18 22:14:47 来源:WEB开发网核心提示:原帖子: http://www.chinaunix.net/forum/viewtopic.php?t=62859 在db2里面有import命令,是用来装载文本数据到数据库的,db2定长import API问题解决,与大家分享!!,下面是脚本: import from F:\db2c\PAS-BASS\data\ti
原帖子:
http://www.chinaunix.net/forum/viewtopic.php?t=62859
在db2里面有import命令,是用来装载文本数据到数据库的。下面是脚本:
import from F:\db2c\PAS-BASS\data\ticket\realdata\ OF ASC MODIFIED BY noeofchar nullindchar=Y timestampformat="YYYYMMDDhhmmss" METHOD L ( 1 1,2 21,22 36,37 40,41 54,55 55,56 75 INSERT INTO LAW.APTI_FULL_ITEM
现在我们要用db2提供的api,sqluimpr()来实现那个命令。这个函数里面有很多参数,那些参数是用来记录脚本里面的命令参数的,比如文件路径 是char类型,消息文件路径是 char 类型,import的文件类型 sqlchar数据类型等等。
现在我们只关心import api 函数里面有两个参数
struct sqldcol *DataDescriptor
struct sqlchar *ActionString;
ActionString 是用来存储imnport方式的,就是存储上面脚本的“ INSERT INTO LAW.APTI_FULL_ITEM”
下面给出 sqlchar 结构:
#undef _SQLOLDCHAR
#ifdef SQLOLDCHAR
#define _SQLOLDCHAR unsigned char
#else
#define _SQLOLDCHAR char
#endif
SQL_STRUCTURE sqlchar
{
short length;
_SQLOLDCHAR data[1];
};
由此看来 sqlchar.short 是用来存储字符串长度的,data[1] 是用来存储字符串的,下面是赋值代码:
struct sqlchar *ActionString;
char String[80];
strcpy(String, " INSERT INTO LAW.APTI_FULL_ITEM");
ActionString = (struct sqlchar *)
malloc (strlen(String) + sizeof(struct sqlchar));
ActionString->length = strlen(String);
strncpy(ActionString->data, String, strlen(String));
这句话:
strncpy(ActionString->data, String, strlen(String));
明明data是只有一个长度的字符数组,怎么能存储一个长度大于1的字符串string那?
-------------------------------------
实际上是这样的,网上有人回答了:(http://expert.csdn.net/Expert/topic/1754/1754927.xml(标准化越来越近了)?temp=.7425043 )
0。
原来(好像很久以前了)c语言中常用的一种惯用法。
他用 char[1]来代替不定长的字符串。比加一个指针在使用上要方便许多。
这种方法通过分配内存时候,多分配几个字节,来解决数组不定长的问题。
好像在 《C++物件模型》 中有介绍。不然的话,就看看介绍 c 惯用法方面的书吧
1。
实际上代码没有错误。
ActionString = (struct sqlchar *)
malloc (strlen(String) + sizeof(struct sqlchar));
分配了足够的空间(串长+结构大小)
2。
之所以如此写代码,是为了其同用性,不会因为
char String[80];
的大小,去改变
_SQLOLDCHAR data[1];
的大小。
3。
--_SQLOLDCHAR data[1];
这种定义确实和语义不符,但也是一种常用的方法。
在很久很久以前,可以将未知长度的数组定义为:
DATATYPE array[];
将其定义为“SQLOLDCHAR data[1]”,其实就是说明“data”是一个数组。
应用的时候,数组的实际长度是和分配的内存大小相关的。
--ActionString = (struct sqlchar *)malloc(strlen(String) + sizeof(struct sqlchar));
这一句,分配的内存包括了需要拷贝字符串的长度,sqlchar结构的大小(字符串的结束字符“0”也考虑了),就这一段代码来看,并没有问题。
另外,这段代码分配内存用的是“malloc”,而不是C++常用的“new”。这一点需要注意。
-------------------------------------------------------------------------
现在我遇到难题了,本来想按照上面的方法给DataDescriptor赋值的时候发现,结构体变复扎了:
DataDescripto 使用来存储import方式的,使用方法L , P或者 D这三个其中的一种。
L:使用asc文件格式的定长import。(就是文件数据每个字段都是占用定长的,不够长度用空格补起)。
P:使用DEL格式的字段对应import
我们不管P 和D,上面的import脚本就是用的定长格式,脚本里面的语句:
METHOD L ( 1 1,2 21,22 36,37 40,41 54,55 55,56 75
就说明了,import方法是L ,并且在后面给出了每个字段的在文件的开始位置和结束位置如:第二字段的开始位置是2 结束位置是21。
所以我们要告诉api这下信息。
包含这些信息的参数是:
struct sqldcol *DataDescriptor
db2 api这本书里面是这样说赋值的:
有个变量是DataDescriptor,DataDescriptor 的dcolmeth字段就被赋值成SQL_METH_L,dcolname数组中的第一个元素的dcolnptr指针指向包含sqllocpair结构数组的sqlloctab结构。此数组中的元素的数量必须存储在sqlcol结构的dcolnum字段中。在数组的每个元素必须包含一对整型数值,用来只是在文件中列开始和结束的位置。整型数据中的第一个值是在文件中列开始的字节位置(在第一行中),第二个值是在文件中列结束的字节位置(在同一行中)。第一个字节值可被设置位1(指示在一行数据中的第一个字节),可以设置的最大的字节的位置是由外部文件的第一行数据中所包含的字节数决定。
结构体如下
SQL_STRUCTURE sqldcoln
{
short dcolnlen; /*dcolnptr字段所指定的数据元数大小*/
char *dcolnptr; /*一个指向内存中的某个位置的,在这块内存区域中,存放sqldcol结构的dcolmeth字段所指定的数据元数*/
};
SQL_STRUCTURE sqldcol
{
short dcolmeth;
short dcolnum;
struct sqldcoln dcolname[1]; /* actual size must be dcolnum */
};
/* Structure for Pairs of Locations for ASC files */
SQL_STRUCTURE sqllocpair
{
short begin_loc; /*在数据文件中的列数据的开始位置*/
short end_loc; /*在数据文件中的列数据的结束位置*/
};
SQL_STRUCTURE sqlloctab
{
struct sqllocpair locpair[1]; /*一个指向sqllocpair结构数组的指针,该数组包含个个列的开始位置和结束位置, actual size must be dcolnum */
};
DataDescriptor->dcolmeth
dcolnum
dcolname[1]->dcolnlen
char *dcolnptr->(这里强制指向结构)sqllocpair locpair[1]->begin_loc
end_loc
现在是如何给他们赋值那?
经过我不懈得测试,最后得出,存储列的开始位置和结束位置的数组是这个结构
sqllocpair locpair[1]
但是他定义的时候只有一个长度,那么就需要我们按照IBM的方法给他赋值了!
[/code]
/*初始化DataDescriptor 结构很复杂注意释放内存*/
DataDescriptor=(struct sqldcol *) malloc(sizeof(struct sqldcol));
DataDescriptor->dcolmeth=SQL_METH_L;
DataDescriptor->dcolnum=colnum;
if ( DataDescriptor==NULL)
{printf("ERROR while malloc DataDescriptor"); exit(0);}
/*为存放列信息的结构体分配内存,强制转换char *指向 sqlloctab*/
DataDescriptor->dcolname[0].dcolnptr=(struct sqlloctab *)malloc(colnum*sizeof(struct sqlloctab));
/*k 分配内存的变量*/
k=0; /*k是存放列数*/
for (i=0;i<k;i++)
{/*计算出每个列的开始位子和结束位置 X Y
*/
/*分配DataDescriptor 的成员*/
((struct sqlloctab *)((*DataDescriptor).dcolname[0].dcolnptr))->locpair[k].begin_loc=x;
((struct sqlloctab *)((*DataDescriptor).dcolname[0].dcolnptr))->locpair[k].end_loc=y;
(*DataDescriptor).dcolname[0].dcolnlen=strlen((*DataDescriptor).dcolname[0].dcolnptr);
/*注意,这里用了强制类型转换
因为char (*DataDescriptor).dcolname[0].dcolnptr 但是IBM的API里面说他是指向一个内存区域,实际上就是一个结构,所以我们强制把他指向一个结构SQL_STRUCTURE sqlloctab */
/*调用API*/
importl(TName,fullname,msgfile,choose,DataDescriptor);
}
结束
[/code]
- ››db2 对float类型取char后显示科学计数法
- ››DB2中出现SQL1032N错误现象时的解决办法
- ››DB2 锁升级示例
- ››db2诊断系列之---定位锁等待问题
- ››db2 命令选项解释
- ››DB2 最佳实践: 使用 DB2 pureXML 管理 XML 数据的...
- ››DB2 9.5 SQL Procedure Developer 认证考试 735 准...
- ››DB2 9.5 SQL Procedure Developer 认证考试 735 准...
- ››DB2 9.5 SQL Procedure Developer 认证考试 735 准...
- ››DB2 基础: 表空间和缓冲池
- ››DB2 XML 编程,第 1 部分: 理解 XML 数据模型
- ››DB2 pureScale 实战
更多精彩
赞助商链接