用C++ 产生 SQL*Loader 各类文件
【IT168服务器学院】1.前言
目前,我国许多单位MIS系统建立在微机PC或基于NovellNetWare局域网环境中,数据库和开发工具采用Foxpro2.5forDOS或Foxpro2.5forWindows,以dbf文件为数据组织管理手段,随着系统的不断扩大和实际应用的需要,不少单位已开始采用大型数据库Oracle。在MIS从Foxpro升级到大型数据库Oracle过程中,将Foxpro的dbf文件通过Oracle工具SQL*Loader加载到Oracle数据库中是一项非常重要的工作。一般用SQL*Loader加载的具体实施步骤是:
*运行Foxpro,打开数据库,将dbf文件拷贝为SDF格式的文本文件
*根据dbf文件结构,产生建立Oracle表(CREATETABLE)的SQL语句
*登录Oracle,运行产生Oracle表(CREATETABLE)的SQL语句
*根据dbf文件结构,产生SQL*Loader的控制文件
*运行SQL*Loader,加载数据
用手工方法产生CREATETABLE的SQL语句,特别是产生SQL*Loader控制文件时,POSITION起始、结束位置经常弄错,当需要加载大量的数据时,不但烦琐,而且效率比较低。我们在实践中利用BorlandC++5.0编制了一个C++实用程序load.cpp,自动产生SQL*Loader的数据文件、控制文件和产生CREATETABLE的SQL语句。运用load,我们只需:
*load<数据库名>
*登录Oracle,运行产生Oracle表(CREATETABLE)的SQL语句
*运行SQL*Loader,加载数据
在实践中,我们通过这种方法,在实现从Foxpro到OracleforDigitalUNIX+中文Windows95的client/server平台的数据加载过程中提高了效率。
2.Foxpro中dbf文件结构
dbf文件由文件头和文件记录组成,其中文件头又由数据库说明和字段说明组成。数据库说明由32个字节组成,各字节含义见表一:
字节
含义
0
数据库文件标志有无备注型字段(03H无)
1-3
最后一次修改日期
4-7
文件记录数
8-9
文件头长度
10-11
记录长度
12-31
未用
表一
字段说明由若干个32字节组成,每32字节说明一个字段,各字节含义见表二:
字节
含义
0-10
字段名
11
字段类型
12-15
该字段在文件首记录中的地址
16
字段长度
17
小数位数
18-31
未用
表二
文件记录以ASCII形式存储,每条记录以空格(20H)开头,该空格用来作删除标志用。
3.建立对应Foxpro的Oracle表的SQL语句
Foxpro和Oracle对应的数据类型的描述见表三:
Foxpro
Oracle
Character(n)
char(n)varchar2(n)
Number(n,m)
number(n-1,m)m<>0
number(n,m)m=0
Float(n,m)
Logical
char(1)
DATE
DATE
三
【注】:
*不考虑完整性约束,同时对于TABLESPACE及STORAGE存储参数取缺省值。
*对于数字型字段,n表示数字的宽度,在Foxpro中包含小数点位置,而在Oracle中不包含。
*对于Foxprological型字段类型,由于Oracle中没有相应的逻辑型变量,故将其转换为字符类型。
*暂且不考虑memo、general、picture字段的转换。
4.SQL*Loader控制文件的建立
控制文件为SQL*Loader的核心文件,与Foxpro字段对应关系为表四:Foxpro数据类型
控制文件语句对应的格式
Character(n)
CHAR
Number(n,m)
Float(n,m)
DECIMALEXTERNALNULLIF<field>=BLANKS(m<>0)
INTEGEREXTERNALNULLIF<field>=BLANKS(m=0)
Logical
CHAR
DATE
DATE"YYYYMMDD"NULLIF<field>=BLANKS
四
以下是用BorlandC++5.0在中文Windows95下编制的产生CREATETABLESQL语句和产生SQL*Loader数据文件、控制文件的源程序load.cpp。
#include<stdio.h>
#include<stdlib.h>
#include<iostream.h>
#include<fstream.h>
#include<string.h>
#include<math.h>
#defineMAX_ROW_LENGTH1200
#defineMAX_FIELD_NUMBER30
typedefstructhead//dbf头文件结构
{unsignedcharmask;
unsignedchardate[3];
unsignedlongrecord_num;
unsignedshortinthead_length;
unsignedshortintfield_length;
}HEAD;
typedefstructfield//dbf字段结构
{unsignedcharname[11];
unsignedchartype;
unsignedlongadd;
unsignedcharlength;
unsignedchardec;
}FIELD;
intmain(intargc,char**argv)
{charbuf[MAX_ROW_LENGTH],dbf[40],*sqlload;
unsignedinti,field_num;
HEAD*dbfhead;
FIELDdbffield[MAX_FIELD_NUMBER];
FILE*fout,*fp;
if(argc!=2)
{cout<<"Usage:loaddbfile"<<endl;
return-1;
}
sqlload=newchar(40);
dbfhead=newHEAD;
strcpy(buf,"");
strcpy(dbf,argv[1]);
strcat(dbf,".dbf");
if((fp=fopen(dbf,"rb"))==NULL)
{cout<<"Cannotopenfile"<<dbf<<endl;
return-1;
}
fseek(fp,0,SEEK_SET);
fread(dbfhead,sizeof(HEAD),1,fp);//读dbf头文件信息
field_num=(dbfhead->head_length-1)/32-1;//字段个数
for(i=0;i<field_num;i++)
{fseek(fp,32*(i+1),SEEK_SET);
fread(&dbffield[i],sizeof(FIELD),1,fp);//读dbf结构信息
}
//产生SQL*Loader控制文件
strcpy(sqlload,argv[1]);
strcat(sqlload,".ctl");
if((fout=fopen(sqlload,"w"))==NULL)
{cout<<"Cannotopenfile"<<sqlload<<endl;
return-1;
}
fprintf(fout,"LOADDATA\n");
fprintf(fout,"INFILE''%s.txt''\n",argv[1]);
fprintf(fout,"INTOTABLE%s(\n",argv[1]);
for(i=0;i<field_num;++i)
{fprintf(fout,"%11sPOSITION(%d:%d)",dbffield[i].name,
dbffield[i].add,dbffield[i].add+dbffield[i].length-1);
switch(dbffield[i].type)
{case''C'':
case''L''://字符型/逻辑型
fprintf(fout,"CHAR");
break;
case''N'':
if(dbffield[i].dec==0)//整数型
fprintf(fout,"INTEGEREXTERNALNULLIF%s=BLANKS",
dbffield[i].name);
else//实数型
fprintf(fout,"DECIMALEXTERNALNULLIF%s=BLANKS",
dbffield[i].name);
break;
case''D''://日期型
fprintf(fout,"DATE''YYYYMMDD''NULLIF%s=BLANKS",
dbffield[i].name);
break;
default:
break;
}
if(i<field_num-1)
fprintf(fout,",\n");
}
fprintf(fout,")\n");
fclose(fout);
//产生CREATETABEL.的SQL语句
strcpy(sqlload,argv[1]);
strcat(sqlload,".sql");
if((fout=fopen(sqlload,"w"))==NULL)
{cout<<"Cannotopenfile"<<sqlload<<endl;
return-1;
}
fprintf(fout,"createtable%s(\n",argv[1]);
for(i=0;i<field_num;i++)
{fprintf(fout,"%11s",dbffield[i].name);
switch(dbffield[i].type)
{case''C''://字符型
fprintf(fout,"CHAR(%d)",dbffield[i].length);
break;
case''L''://逻辑型
fprintf(fout,"CHAR(1)");
break;
case''N''://数字型
if(dbffield[i].dec==0)
fprintf(fout,"NUMBER(%d)",dbffield[i].length);
else
fprintf(fout,"NUMBER(%d,%d)",
dbffield[i].length-1,dbffield[i].dec);
break;
case''D''://日期型
fprintf(fout,"DATE");;
break;
default:
break;
}
if(i<field_num-1)
fprintf(fout,",\n");
}
fprintf(fout,")\n");
fclose(fout);
//产生SQL*Loader数据文件
strcpy(sqlload,argv[1]);
strcat(sqlload,".txt");
if((fout=fopen(sqlload,"w"))==NULL)
{cout<<"Cannotopenfile"<<sqlload<<endl;
return-1;
}
fseek(fp,dbfhead->head_length,SEEK_SET);
for(i=0;i<dbfhead->record_num;i++)
{fread(buf,dbfhead->field_length,1,fp);
buf[dbfhead->field_length]=''\0'';
fprintf(fout,"%s\n",buf+1);//skip记录首字节(删除标志)
}
fclose(fout);
fclose(fp);
deletesqlload;
return0;
}
目前,我国许多单位MIS系统建立在微机PC或基于NovellNetWare局域网环境中,数据库和开发工具采用Foxpro2.5forDOS或Foxpro2.5forWindows,以dbf文件为数据组织管理手段,随着系统的不断扩大和实际应用的需要,不少单位已开始采用大型数据库Oracle。在MIS从Foxpro升级到大型数据库Oracle过程中,将Foxpro的dbf文件通过Oracle工具SQL*Loader加载到Oracle数据库中是一项非常重要的工作。一般用SQL*Loader加载的具体实施步骤是:
*运行Foxpro,打开数据库,将dbf文件拷贝为SDF格式的文本文件
*根据dbf文件结构,产生建立Oracle表(CREATETABLE)的SQL语句
*登录Oracle,运行产生Oracle表(CREATETABLE)的SQL语句
*根据dbf文件结构,产生SQL*Loader的控制文件
*运行SQL*Loader,加载数据
用手工方法产生CREATETABLE的SQL语句,特别是产生SQL*Loader控制文件时,POSITION起始、结束位置经常弄错,当需要加载大量的数据时,不但烦琐,而且效率比较低。我们在实践中利用BorlandC++5.0编制了一个C++实用程序load.cpp,自动产生SQL*Loader的数据文件、控制文件和产生CREATETABLE的SQL语句。运用load,我们只需:
*load<数据库名>
*登录Oracle,运行产生Oracle表(CREATETABLE)的SQL语句
*运行SQL*Loader,加载数据
在实践中,我们通过这种方法,在实现从Foxpro到OracleforDigitalUNIX+中文Windows95的client/server平台的数据加载过程中提高了效率。
2.Foxpro中dbf文件结构
dbf文件由文件头和文件记录组成,其中文件头又由数据库说明和字段说明组成。数据库说明由32个字节组成,各字节含义见表一:
字节
含义
0
数据库文件标志有无备注型字段(03H无)
1-3
最后一次修改日期
4-7
文件记录数
8-9
文件头长度
10-11
记录长度
12-31
未用
表一
字段说明由若干个32字节组成,每32字节说明一个字段,各字节含义见表二:
字节
含义
0-10
字段名
11
字段类型
12-15
该字段在文件首记录中的地址
16
字段长度
17
小数位数
18-31
未用
表二
文件记录以ASCII形式存储,每条记录以空格(20H)开头,该空格用来作删除标志用。
3.建立对应Foxpro的Oracle表的SQL语句
Foxpro和Oracle对应的数据类型的描述见表三:
Foxpro
Oracle
Character(n)
char(n)varchar2(n)
Number(n,m)
number(n-1,m)m<>0
number(n,m)m=0
Float(n,m)
Logical
char(1)
DATE
DATE
三
【注】:
*不考虑完整性约束,同时对于TABLESPACE及STORAGE存储参数取缺省值。
*对于数字型字段,n表示数字的宽度,在Foxpro中包含小数点位置,而在Oracle中不包含。
*对于Foxprological型字段类型,由于Oracle中没有相应的逻辑型变量,故将其转换为字符类型。
*暂且不考虑memo、general、picture字段的转换。
4.SQL*Loader控制文件的建立
控制文件为SQL*Loader的核心文件,与Foxpro字段对应关系为表四:Foxpro数据类型
控制文件语句对应的格式
Character(n)
CHAR
Number(n,m)
Float(n,m)
DECIMALEXTERNALNULLIF<field>=BLANKS(m<>0)
INTEGEREXTERNALNULLIF<field>=BLANKS(m=0)
Logical
CHAR
DATE
DATE"YYYYMMDD"NULLIF<field>=BLANKS
四
以下是用BorlandC++5.0在中文Windows95下编制的产生CREATETABLESQL语句和产生SQL*Loader数据文件、控制文件的源程序load.cpp。
#include<stdio.h>
#include<stdlib.h>
#include<iostream.h>
#include<fstream.h>
#include<string.h>
#include<math.h>
#defineMAX_ROW_LENGTH1200
#defineMAX_FIELD_NUMBER30
typedefstructhead//dbf头文件结构
{unsignedcharmask;
unsignedchardate[3];
unsignedlongrecord_num;
unsignedshortinthead_length;
unsignedshortintfield_length;
}HEAD;
typedefstructfield//dbf字段结构
{unsignedcharname[11];
unsignedchartype;
unsignedlongadd;
unsignedcharlength;
unsignedchardec;
}FIELD;
intmain(intargc,char**argv)
{charbuf[MAX_ROW_LENGTH],dbf[40],*sqlload;
unsignedinti,field_num;
HEAD*dbfhead;
FIELDdbffield[MAX_FIELD_NUMBER];
FILE*fout,*fp;
if(argc!=2)
{cout<<"Usage:loaddbfile"<<endl;
return-1;
}
sqlload=newchar(40);
dbfhead=newHEAD;
strcpy(buf,"");
strcpy(dbf,argv[1]);
strcat(dbf,".dbf");
if((fp=fopen(dbf,"rb"))==NULL)
{cout<<"Cannotopenfile"<<dbf<<endl;
return-1;
}
fseek(fp,0,SEEK_SET);
fread(dbfhead,sizeof(HEAD),1,fp);//读dbf头文件信息
field_num=(dbfhead->head_length-1)/32-1;//字段个数
for(i=0;i<field_num;i++)
{fseek(fp,32*(i+1),SEEK_SET);
fread(&dbffield[i],sizeof(FIELD),1,fp);//读dbf结构信息
}
//产生SQL*Loader控制文件
strcpy(sqlload,argv[1]);
strcat(sqlload,".ctl");
if((fout=fopen(sqlload,"w"))==NULL)
{cout<<"Cannotopenfile"<<sqlload<<endl;
return-1;
}
fprintf(fout,"LOADDATA\n");
fprintf(fout,"INFILE''%s.txt''\n",argv[1]);
fprintf(fout,"INTOTABLE%s(\n",argv[1]);
for(i=0;i<field_num;++i)
{fprintf(fout,"%11sPOSITION(%d:%d)",dbffield[i].name,
dbffield[i].add,dbffield[i].add+dbffield[i].length-1);
switch(dbffield[i].type)
{case''C'':
case''L''://字符型/逻辑型
fprintf(fout,"CHAR");
break;
case''N'':
if(dbffield[i].dec==0)//整数型
fprintf(fout,"INTEGEREXTERNALNULLIF%s=BLANKS",
dbffield[i].name);
else//实数型
fprintf(fout,"DECIMALEXTERNALNULLIF%s=BLANKS",
dbffield[i].name);
break;
case''D''://日期型
fprintf(fout,"DATE''YYYYMMDD''NULLIF%s=BLANKS",
dbffield[i].name);
break;
default:
break;
}
if(i<field_num-1)
fprintf(fout,",\n");
}
fprintf(fout,")\n");
fclose(fout);
//产生CREATETABEL.的SQL语句
strcpy(sqlload,argv[1]);
strcat(sqlload,".sql");
if((fout=fopen(sqlload,"w"))==NULL)
{cout<<"Cannotopenfile"<<sqlload<<endl;
return-1;
}
fprintf(fout,"createtable%s(\n",argv[1]);
for(i=0;i<field_num;i++)
{fprintf(fout,"%11s",dbffield[i].name);
switch(dbffield[i].type)
{case''C''://字符型
fprintf(fout,"CHAR(%d)",dbffield[i].length);
break;
case''L''://逻辑型
fprintf(fout,"CHAR(1)");
break;
case''N''://数字型
if(dbffield[i].dec==0)
fprintf(fout,"NUMBER(%d)",dbffield[i].length);
else
fprintf(fout,"NUMBER(%d,%d)",
dbffield[i].length-1,dbffield[i].dec);
break;
case''D''://日期型
fprintf(fout,"DATE");;
break;
default:
break;
}
if(i<field_num-1)
fprintf(fout,",\n");
}
fprintf(fout,")\n");
fclose(fout);
//产生SQL*Loader数据文件
strcpy(sqlload,argv[1]);
strcat(sqlload,".txt");
if((fout=fopen(sqlload,"w"))==NULL)
{cout<<"Cannotopenfile"<<sqlload<<endl;
return-1;
}
fseek(fp,dbfhead->head_length,SEEK_SET);
for(i=0;i<dbfhead->record_num;i++)
{fread(buf,dbfhead->field_length,1,fp);
buf[dbfhead->field_length]=''\0'';
fprintf(fout,"%s\n",buf+1);//skip记录首字节(删除标志)
}
fclose(fout);
fclose(fp);
deletesqlload;
return0;
}
0
相关文章