Chinaunix首页 | 论坛 | 博客
  • 博客访问: 15260553
  • 博文数量: 7460
  • 博客积分: 10434
  • 博客等级: 上将
  • 技术积分: 78178
  • 用 户 组: 普通用户
  • 注册时间: 2008-03-02 22:54
文章分类

全部博文(7460)

文章存档

2011年(1)

2009年(669)

2008年(6790)

分类: C/C++

2008-05-31 10:24:50

----目前,我国许多单位MIS系统建立在微机PC或基于NovellNetWare局域网环境中,数据库和开发工具采用Foxpro2.5 for DOS或Foxpro 2.5 for ,以dbf文件为数据组织管理手段,随着系统的不断扩大和实际应用的需要,不少单位已开始采用大型数据库。在MIS从Foxpro升级到大型数据库过程中,将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+中文95的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  POSITION(%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                               //实数型
          fprintf(fout, \"  DECIMAL EXTERNAL NULLIF %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);// 产 生CREATE TABEL. 的SQL 语 句
  strcpy(sqlload,argv[1]);
  strcat(sqlload,\".sql\");
  if ((fout=fopen(sqlload,\"w\")) == NULL)
  { cout < < \"Cannot open file \" < < sqlload < < endl;
    return -1 ;
  }
  fprintf(fout, \"create table %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 < < \"Cannot open file \" < < 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);

  delete sqlload;
  return 0 ;
}

阅读(266) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~