程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> 關於C++ >> 用C++產生QL*Loader各類文件

用C++產生QL*Loader各類文件

編輯:關於C++

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控制文件時,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)開頭,該空格用來作刪除標志用。

【注】:

* 不考慮完整性約束,同時對於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 ;
}

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved