ETL应用:使用Pro*C写入文件信息入库的方法

时间:2021-11-30 17:51:01

     ETL处理过程中,经常需要进行文件校验,如文件级校验、记录级校验,需要保存文件的基本信息,文件名、文件大小、数据日期等,使用Pro*C的一种方法如下:

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>
#include <limits.h>
#include <sqlda.h>
#include <sqlcpr.h> 
/*定义数据库连接信息*/
#define USERNAME    "masaetl"
#define PASSWORD    "masaetl"
#define ORACLESID   "DWDB2"
/*定义数据存放目录,这些目录是链接文件的目录*/
char data_dir[5][64]={ "/ETL_FS/etlfs/interface/boss/input/day_full",
                     "/ETL_FS/etlfs/interface/boss/input/day_incr",
                     "/ETL_FS/etlfs/interface/boss/input/oth_full",
                     "/ETL_FS/etlfs/interface/boss/input/oth_incr",
                     "/ETL_FS/etlfs/interface/kf_data/link"
};     
/*定义处理日期,内部链接的静态变量*/
static char filedate[9];
/*调试代码时使用*/
#ifndef DEBUG
#define DEBUG   // 定义调试开关
#endif
/*SQL语句返回值定义*/
/*定义返回值,成功为0,错误<0,警告>0  */
#define SQLCODE   sqlca.sqlcode      
/*SQL语句返回错误解释 */
#define SQLERRMC  sqlca.sqlerrm.sqlerrmc     
/*包含数据库信息*/
EXEC SQL INCLUDE sqlca;
EXEC SQL INCLUDE sqlda;
/*SQL语句返回值定义*/
/*定义返回值,成功为0,错误<0,警告>0*/
#define SQLCODE   sqlca.sqlcode   
/*SQL语句返回错误解释*/  
#define SQLERRMC  sqlca.sqlerrm.sqlerrmc     
void sqlerror();           /*处理SQL错误*/
int ConnectDataBase();     /*链接数据库*/
void DisConnectDataBase(); /*断开数据库连接*/
char *getYestDate(char *szDate);   /*得到前一天的日期,格式"YYYYMMDD"*/
char *getFileName(const char *szFilePath,char *szFileName); /*从字符串中得到文件名*/
/**************************************
*** 功能: 提取运行在数据库级报错信息
*** 输入变量:
*** 输出变量:
***************************************/
void sqlerror()
{
   /*为了避免错误处理时发生死循环,应给出此说明*/
   EXEC SQL WHENEVER SQLERROR CONTINUE;
   printf("\n Oracle error detected: ");
   printf("\n%s",SQLERRMC);  /*错误信息*/
   
   /*断开数据库链接*/
   EXEC SQL ROLLBACK WORK RELEASE;
   exit(1);
}
/**************************************
*** 功能:  连接数据库
*** 输入变量:
*** 输出变量: -1 连接数据库失败 0 成功
***************************************/
int ConnectDataBase()
{
  EXEC SQL BEGIN DECLARE SECTION;
          char  username[8];
          char  password[11];
          char  oraclesid[7];
    EXEC SQL END DECLARE  SECTION;
    
  strcpy(username,USERNAME);  /*用户名*/
   //username.len=strlen(username.arr);
   
   strcpy(password,PASSWORD);  /*密码*/
   //password.len=strlen(password.arr);
   
   strcpy(oraclesid,ORACLESID);  /*Oralce SID*/
   //oraclesid.len=strlen(oraclesid.arr);
   
   /*链接数据库*/
   EXEC SQL CONNECT :username IDENTIFIED BY :password USING :oraclesid; 
   if( SQLCODE ) { 
    
     return -1;
    }
   return 0; 
}
/**************************************
*** 功能:  断开数据库连接
*** 输入变量:
*** 输出变量: 
***************************************/
void DisConnectDataBase()
{
  /*断开连接*/
EXEC SQL ROLLBACK WORK RELEASE;
  exit(0);
}
/***************************************
**  功能 :    得到前一天的日期
*** 输入变量:
*** 输出变量: 
****************************************/
char *getYestDate(char *szDate)
{
   time_t yest;
   struct tm ptime={'\0'};
   char szChar[5];
     
   //若输入的参数为空,默认提取系统前一天的日期
   if ( *szDate =='\0' ){
      
      yest=time(NULL)-(time_t)(60*60*24);
      strftime(szDate,9,"%Y%m%d",localtime(&yest));
       
      return szDate;
     }
   //提取年
   memset(szChar,0,sizeof(szChar));
   strncpy(szChar,szDate,4);
   ptime.tm_year=atoi(szChar)-1900;
     
   //提取月
   memset(szChar,0,sizeof(szChar));
   strncpy(szChar,szDate+4,2);
   ptime.tm_mon=atoi(szChar)-1;
     
   //提取日
   memset(szChar,0,sizeof(szChar));
   strncpy(szChar,szDate+6,2);
   ptime.tm_mday=atoi(szChar);
     
   yest=mktime(&ptime)-(time_t)(60*60*24);
   strftime(szDate,9,"%Y%m%d",localtime(&yest));
     
   return szDate;
}
/***************************************
**  功能 :    从文件路径中得到文件名称(去掉前面的路径)
*** 输入变量:文件路径
*** 输出变量:文件名
****************************************/
char *getFileName(const char *szFilePath,char *szFileName)
{
    char *szPtr;
    
    const char separator='/';   /*定义分隔符*/
    szPtr=strrchr(szFilePath,separator);   /*查找最后一个子串*/
    
    if ( szPtr ){
     
       szFileName=szPtr+1;
     }
#ifdef DEBUG
   printf("文件名称为: [%s]",szFileName);     
#endif
    return szFileName;
}
/***************************************
**  功能 :    主程序
****************************************/
int main( void )
{
int i=0;
char *szOrderId;
char pFileName[128];
char *filename;         //文件名
char szDate[15];        //日期 "yyyymmddhh24miss"
time_t  file_mtime;     //文件时间

struct stat st;
struct dirent *dirp;
DIR    *pDirectory;

/*定义数据库变量*/
EXEC SQL BEGIN DECLARE SECTION;
      char    file_date[9];             //文件日期
      long    orderid;                  //序号(接口编号)
      char    file_name[30];            //文件名称
      long    file_size;                //文件大小
      char    file_create_date[15];     //文件最后修改的时间
EXEC SQL END DECLARE SECTION;

/*链接数据库*/
if( ConnectDataBase()<0 ){
  
    printf("连接数据失败.\n");
}

/*得到处理日期*/
getYestDate(filedate);
strcpy(file_date,filedate);
#ifdef DEBUG
   printf("处理日期: [%s].\n",file_date);     
#endif
  /*删除当日已统计数据*/
   EXEC SQL DELETE FROM
          MASAETL.ETL_LINK_FILE WHERE FILEDATE=:file_date;
           
  /*处理执行SQL异常*/
   if ( 1403!=SQLCODE && 0!=SQLCODE ){
    
#ifdef DEBUG
    printf("删除当日统计数据失败,原因为:[%d]:[%s]\n",SQLCODE,SQLERRMC);
#endif
       EXEC SQL ROLLBACK;
       DisConnectDataBase();
       exit(1);
   }
  /*提交删除信息*/
   EXEC SQL COMMIT;   
     
/*循环处理目录下的文件*/
  for(  i=0; i<5; i++)                 //while ( *data_dir[i++] )
  {
   if ( (pDirectory=opendir(data_dir[i]))==NULL ){
    
          printf("打开目录[%s]失败.\n",data_dir[i]);
          continue;    
   }
   
   while( (dirp=readdir(pDirectory))!=NULL ){
    
   if (strcmp(dirp->d_name,".")==0 ||
      strcmp(dirp->d_name,"..")==0)
      {
       continue;
     } 
        
   sprintf(pFileName,"%s/%s",data_dir[i],dirp->d_name);
   
#ifdef DEBUG
   printf("文件名为: [%s].\n",dirp->d_name);     
#endif
   
   if( stat(pFileName,&st) <0 ){
    
      printf("读文件[%s]到文件结构失败.\n",dirp->d_name);
      continue;
   }
   /*得到文件最后修改时间*/   
   file_mtime=st.st_mtime;
   strftime(szDate,15,"%Y%m%d%H%S",localtime(&file_mtime));
   strcpy(file_create_date,szDate);   
   
   /*得到文件大小*/
   file_size=st.st_size;
   
   /*得到文件名*/   
   //getFileName(szFileName,filename);
   strcpy(file_name,dirp->d_name);
   
   /*得到接口序号*/
   strncpy(szOrderId,file_name+1,5);
   szOrderId[6]='\0';
   orderid=atol(szOrderId);
   
   /*将文件信息入库*/
   EXEC SQL INSERT
   INTO MASAETL.ETL_LINK_FILE(FILEDATE,ORDER_ID,FILENAME,FILECREATEDATE,FILESIZE)
      VALUES(:file_date, :orderid, :file_name,TO_DATE( :file_create_date,'YYYYMMDDHH24MISS'), :file_size);
   
   /*处理执行SQL异常*/
   if ( SQLCODE ){
    
#ifdef DEBUG
    printf("向数据库中写入文件信息失败,原因为:[%d]:[%s]\n",SQLCODE,SQLERRMC);
#endif
       EXEC SQL ROLLBACK;
       continue;
   }
   /*提交录入信息*/
   EXEC SQL COMMIT; 
  }
   /*关闭目录*/
   closedir(pDirectory);        
  }
  
  /*断开数据库连接*/
  DisConnectDataBase();
  return 0;
}