----1.前言
----目前,我国许多单位MIS系统建立在微机PC或基于NovellNetWare局域网环境中,数据库和开发工具采用FoXPro2.5 for DOS或Foxpro 2.5 for Windows,以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控制文件时,POS99vION起始、结束位置经常弄错,当需要加载大量的数据时,
不但烦琐,而且效率比较低。我们在实践中利用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)开头,该空格用来作删除标志用。
----三
----【注】:
----* 不考虑完整性约束,同时对于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)
DECIMAL EXTERNAL NULLIF < field > = BLANKS (m< >0)
INTEGER EXTERNAL NULLIF < field > = BLANKS ( m=0)
Logical
CHAR
DATE
DATE "YYYYMMDD" NULLIF < field > = BLANKS
---- 四
---- 以 下 是 用Borland C++ 5.0 在 中 文Windows 95 下 编 制 的 产 生CREATE TABLE SQL 语 句 和 产 生SQL*Loader 数 据 文 件、 控 制
文 件 的 源 程 序load.cpp。
#include < stdio.h >
#include < stdlib.h >
#include < iostream.h >
#include < fstream.h >
#include < string.h >
#include < math.h >
#define MAX_ROW_LENGTH 1200
#define MAX_FIELD_NUMBER 30
typedef strUCt head // dbf头文件结构
{ unsigned char mask ;
unsigned char date[3] ;
unsigned long record_num;
unsigned short int head_length;
unsigned short int field_length ;
} HEAD ;
typedef struct field // dbf字段结构
{ unsigned char name[11];
unsigned char type ;
unsigned long add;
unsigned char length;
unsigned char dec ;
} FIELD ;
int main(int argc,char **argv)
{ char buf[MAX_ROW_LENGTH],dbf[40],*sqlload;
unsigned int i,field_num;
HEAD *dbfhead ;
FIELD dbffield[MAX_FIELD_NUMBER];
FILE *fout, *fp;
if (argc!=2)
{ cout < < "Usage : load dbfile" < < endl ;
return -1;
}
sqlload = new char(40);
dbfhead = new HEAD;
strcpy(buf,"");
strcpy(dbf,argv[1]);
strcat(dbf,".dbf");
if ((fp=fopen(dbf,"rb")) == NULL)
{ cout < < "Cannot open file " < < 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 < < "Cannot open file " < < sqlload < < endl;
return -1 ;
}
fprintf(fout,"LOAD DATA\n");
fprintf(fout,"INFILE '%s.txt'\n", argv[1]);
fprintf(fout,"INTO TABLE %s (\n", argv[1]);
for(i=0;i< field_num;++i)
{ fprintf(fout, "%11s POS99vION(%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, "INTEGER EXTERNAL NULLIF %s = BLANKS",
dbffield[i].name);
else &