DumpSqlLdr
From Pickwiki
Jump to navigationJump to search
HomePage>>SourceCode>>BasicSource
A program to extract data from UniData, to flat files in a format suitable for import into Oracle, using sqlldr
*************************************************************************** * Program: TRIN.DUMP.SQLLDR * Author : Ian [[McG]] * Date : 12/13/1999 * Edited : 09:52:19 Oct 22 2002 By MGC * Comment: Dump a recall in sql*loader format for transfer to oracle *************************************************************************** * Date By Desc * ---------- ---- --------------------------------------------------------- * 01/18/2000 Ian Run sqlldr after making dump file, delete dmp * 01/21/2000 Ian Send right date format * 02/28/2000 Ian Email log file to dump user when done * 07/15/2000 Ian Check for specific ORACLE.FIELD.SIZE * 07/15/2000 Ian Do not send < or > chars * 03/20/2001 Ian Set oracle_sid based on account * Sample of dump format *LOAD DATA *INFILE * *INTO TABLE dept *REPLACE *FIELDS TERMINATED BY '|' *(deptno,dname,loc) *BEGINDATA *10|ACCOUNTING|NEW YORK *20|RESEARCH|DALLAS *30|SALES|RESTON OPEN 'RECALLS' TO RECALLS ELSE STOP 201,'RECALLS' OPEN 'TRIN.SQLLDR.DATA' TO TRIN.SQLLDR.DATA ELSE STOP 201,'TRIN.SQLLDR.DATA' PROMPT '' S=@SENTENCE RECALL.NAME=FIELD(S, ' ', 2) IF RECALL.NAME = '' THEN PRINT @(-1):'ENTER RECALL NAME: ': INPUT RECALL.NAME IF RECALL.NAME = '' OR RECALL.NAME = '/' THEN STOP END READ RECALL FROM RECALLS, RECALL.NAME ELSE STOP 'CANNOT READ RECALLS ':RECALL.NAME READ SQLREC FROM TRIN.SQLLDR.DATA, RECALL.NAME ELSE STOP 'CANNOT READ TRIN.SQLLDR.DATA ':RECALL.NAME END ORACLE.TABLE.NAME=SQLREC<1> * See if there's a select or get-list statement GOSUB FIND.SELECT.LINE * Get rid of the select line and other stuff RECALL=RECALL<1> DEL RECALL<1,1> OUTFILE.BASE="/samba_share/recall_dump/":RECALL.NAME:"_":OCONV(TIME(),"MT") CONVERT ":" TO "" IN OUTFILE.BASE OUTFILE=OUTFILE.BASE:".DMP" EXECUTE "!rm ":OUTFILE EXECUTE "!touch ":OUTFILE OPENSEQ OUTFILE TO OUTFILE.F ELSE STOP 201,OUTFILE BAD=OUTFILE.BASE:'.DMP.bad' EXECUTE "!rm ":BAD IF SELECT.LINE = '' THEN STOP 'MUST HAVE A SELECT LIST ' PRINT SELECT.LINE EXECUTE SELECT.LINE GOSUB PARSE.ATB.NAMES OUTREC=\LOAD DATA\ ; GOSUB ADD.ROW OUTREC=\INFILE *\ ; GOSUB ADD.ROW OUTREC=\INTO TABLE \:ORACLE.TABLE.NAME GOSUB ADD.ROW OUTREC=\REPLACE\ ; GOSUB ADD.ROW OUTREC=\FIELDS TERMINATED BY '|'\ ; GOSUB ADD.ROW OUTREC=\(\ ; GOSUB ADD.ROW FOR COL=1 TO NUM.FLDS IF COL=1 THEN OUTREC=FLD.LIST<6,COL> END ELSE OUTREC=\,\:FLD.LIST<6,COL> END IF FLD.LIST<2,COL>[1,1]='D' THEN * Dates need format specified OUTREC:=\ DATE "MM[[/DD/YYYY]]"\ END ELSE IF FLD.LIST<7,COL> <> "" THEN OUTREC:=\ char(\:FLD.LIST<7,COL>:\)\ END GOSUB ADD.ROW NEXT COL OUTREC=\)\ ; GOSUB ADD.ROW * Now do the actual data records OUTREC=\BEGINDATA\ ; GOSUB ADD.ROW LOOP READNEXT @ID ELSE EXIT *PRINT @ID READ @RECORD FROM INFILE.F, @ID ELSE STOP 'CANNOT READ ':@ID TEMP.REC='' FOR COL=1 TO NUM.FLDS FLD.NAME=FLD.LIST<1,COL> CNV=FLD.LIST<2,COL> TYP=FLD.LIST<3,COL> ATB=FLD.LIST<4,COL> WID=FLD.LIST<5,COL> IF TYP='D' THEN IF ATB = 0 THEN VALUE=@ID ELSE VALUE=@RECORD<ATB> END ELSE VALUE=CALCULATE(FLD.NAME) END CONVERT "," TO "" IN CNV IF CNV # '*' THEN VALUE=OCONV(VALUE,CNV) IF INDEX(VALUE,@VM,1) THEN * Oh-oh, multivalued CONVERT @VM TO " " IN VALUE END CONVERT \|\ TO \,\ IN VALUE CONVERT \'\ TO \@\ IN VALUE CONVERT \&\ TO \+\ IN VALUE CONVERT \~\ TO \\ IN VALUE CONVERT \<\ TO \[\ IN VALUE CONVERT \>\ TO \]\ IN VALUE TEMP.REC:=TRIM(VALUE):"|" NEXT F * Get rid of trailing delimiter OUTREC=TEMP.REC[1,LEN(TEMP.REC)-1] GOSUB ADD.ROW REPEAT CLOSESEQ OUTFILE.F * Okey dokeley, now to lod the file in with sqlldr CALL TRIN.GET.ACCOUNT(ACCOUNT) BEGIN CASE CASE ACCOUNT='TRINITY' PWD='******' SCHEMA='system1@sunrise' CASE ACCOUNT='STEELCASE' PWD='******' SCHEMA='system2@sunrise' CASE 1 PRINT 'Cannot set [[ORACLE_SID]] - this program must be run' PRINT ' from TRINITY or STEELCASE account' STOP END CASE EXECUTE "!/usr/local/bin/dump_sqlldr ":SCHEMA:" ":PWD:" ":OUTFILE *EXECUTE "!rm ":OUTFILE * Mail the log file to the calling user RECIP=@LOGNAME FRM=@LOGNAME SOURCE=OUTFILE.BASE:'.DMP.log' PRINT "SOURCE: ":SOURCE SUBJECT='SQLLDR log file' OPTIONS='PATH' OPTIONS<2>='UU' *CALL TRIN.MAIL.SUB(RECIP, FRM, SOURCE, SUBJECT, OPTIONS) SUBJECT='SQLLDR errors' CALL TRIN.MAIL.SUB(RECIP, FRM, BAD, SUBJECT, OPTIONS) STOP ADD.ROW: * Write OUTREC to OUTFILE, line at a time WRITESEQ OUTREC APPEND ON OUTFILE.F ELSE STOP 'ERROR WRITING ':OUTFILE RETURN PARSE.ATB.NAMES: PRINT 'Parsing Recall' CONVERT " " TO @VM IN RECALL CONVERT "~" TO "" IN RECALL TOT.FLDS=DCOUNT(RECALL<1>,@VM) NUM.FLDS=0 FLD.LIST='' ; COL.HEAD.LINE='' INFILE='' FOR F=1 TO TOT.FLDS FLD.NAME=RECALL<1,F> * Check this word to see if it's a file name, select, * get-list or dictionary atb IF INFILE='' THEN OPEN FLD.NAME TO DUMMY THEN INFILE=FLD.NAME OPEN INFILE TO INFILE.F ELSE STOP 201,INFILE OPEN 'DICT',INFILE TO @DICT ELSE STOP 201,'DICT ':INFILE CLOSE DUMMY END END ELSE * Add a field to field list, if it's in the dictionary * and it's not already in the list and it's type I or D LOCATE FLD.NAME IN FLD.LIST<1> SETTING POS ELSE * Check to see if this field is mapped to an oracle column name * ...silently discard, if it is not LOCATE FLD.NAME IN SQLREC<2> SETTING POS THEN ORACLE.FIELD.NAME=SQLREC<3,POS> ORACLE.FIELD.SIZE=SQLREC<4,POS> READ DREC FROM @DICT, FLD.NAME THEN IF DREC<1>='I' OR DREC<1>='D' THEN GOSUB STORE.FIELD END END END END NEXT F IF NUM.FLDS = 0 THEN PRINT 'NO ATB NAMES FOUND IN RECALL' STOP END PRINT RETURN STORE.FIELD: NUM.FLDS+=1 COL=NUM.FLDS TYP=DREC<1> ATB=DREC<2> CNV=DREC<3> HED=DREC<4> WID=DREC<5> IF CNV[1,1]='D' THEN CONVERT 'R' TO 'D' IN WID IF CNV='' THEN CNV='*' FLD.LIST<1,COL>=FLD.NAME FLD.LIST<2,COL>=CNV FLD.LIST<3,COL>=TYP FLD.LIST<4,COL>=ATB FLD.LIST<5,COL>=WID FLD.LIST<6,COL>=ORACLE.FIELD.NAME FLD.LIST<7,COL>=ORACLE.FIELD.SIZE IF HED='' THEN HED=FLD.NAME CONVERT @VM TO "_" IN HED CONVERT " " TO "_" IN HED * This is the first line of the output file COL.HEAD.LINE<1,COL>=HED IF DREC<1> # 'D' THEN EXECUTE \CD \:INFILE:\ \:FLD.NAME CAPTURING DUMMY RETURN FIND.SELECT.LINE: SELECT.LINE='' PRE="EXECUTE \" ; LEN.PRE=LEN(PRE) * Skip the first "source" code line LINE.NUM=2 ; MAX.LINE=DCOUNT(RECALL,@AM) LOOP * Strip the line to it's actual code LINE=RECALL<LINE.NUM>[LEN.PRE+1, 999] LINE=FIELD(LINE,'\',1) * Is it a GET.LIST or SELECT? FIRST.WORD=FIELD(TRIM(LINE),' ',1) IF FIRST.WORD='GET.LIST' OR FIRST.WORD='GET-LIST' OR FIRST.WORD='SELECT' OR FIRST.WORD='SSELECT' THEN SELECT.LINE=LINE END UNTIL SELECT.LINE#'' OR LINE.NUM>MAX.LINE DO LINE.NUM += 1 REPEAT RETURN