Professional Documents
Culture Documents
pSrcTable VARCHAR2
,pNaturalKey VARCHAR2
,pTrgTable VARCHAR2
,pSurrogateKey VARCHAR2
,pSequence VARCHAR2
,pOverwriteCols VARCHAR2
,pVersionedCols VARCHAR2
,pStartTS VARCHAR2
,pEndTS VARCHAR2
,pCurrRecFlag VARCHAR2
,pNewRecordsCount OUT NUMBER
,pVersionedRecordsCount OUT NUMBER
,pOverwrittenRecordsCount OUT NUMBER ) IS
mNK dbms_utility.uncl_array;
mOvw dbms_utility.uncl_array;
mVer dbms_utility.uncl_array;
mAll dbms_utility.uncl_array;
mCode dbms_sql.varchar2s;
mItemCnt INTEGER;
PROCEDURE kod( pLinia VARCHAR2 ) IS
BEGIN
-- dbms_output.put_line( pLinia );
mCode( mCode.COUNT+1 ) := pLinia;
END;
PROCEDURE execute_code IS
mCursor INTEGER;
mRowCount NUMBER(9);
BEGIN
mCursor := dbms_sql.OPEN_CURSOR;
dbms_sql.PARSE(mCursor,mCode,1,mCode.COUNT,TRUE,dbms_sql.NATIVE);
dbms_sql.bind_variable(mCursor,'TOTAL_NEW_COUNT',pNewRecordsCount);
dbms_sql.bind_variable(mCursor,'TOTAL_OVW_COUNT',pOverwrittenRecordsCount);
dbms_sql.bind_variable(mCursor,'TOTAL_VER_COUNT',pVersionedRecordsCount);
mRowCount := dbms_sql.EXECUTE(mCursor);
dbms_sql.variable_value(mCursor,'TOTAL_NEW_COUNT',pNewRecordsCount);
dbms_sql.variable_value(mCursor,'TOTAL_OVW_COUNT',pOverwrittenRecordsCount);
dbms_sql.variable_value(mCursor,'TOTAL_VER_COUNT',pVersionedRecordsCount);
dbms_sql.CLOSE_CURSOR(mCursor);
END;
PROCEDURE formatuj_liste2(
pKolumny IN OUT NOCOPY dbms_utility.uncl_array
,pTemplate VARCHAR2
,pSeparator VARCHAR2
,pLimitChars NUMBER DEFAULT 60
,pLimitItems NUMBER DEFAULT 10
,pPrefix VARCHAR2 DEFAULT NULL
,pPostfix VARCHAR2 DEFAULT NULL
,pLinePrefix VARCHAR2 DEFAULT NULL) IS
linia VARCHAR2(255);
chunk VARCHAR2(255);
items NUMBER(5);
BEGIN
linia := pLinePrefix || pPrefix;
items := 0;
FOR i IN pKolumny.FIRST..pKolumny.LAST
LOOP
chunk := replace(pTemplate,'{COL}',pKolumny(i));
IF i < pKolumny.LAST THEN
chunk := chunk || pSeparator;
ELSE
chunk := chunk || pPostfix;
END IF;
IF length(linia) + length(chunk) > pLimitChars OR items=pLimitItems THEN
kod(linia);
linia := pLinePrefix;
items := 0;
END IF;
linia := linia || chunk;
items := items + 1;
END LOOP;
kod(linia);
END;
BEGIN
dbms_utility.COMMA_TO_TABLE(pNaturalKey,mItemCnt,mNK);
dbms_utility.COMMA_TO_TABLE(pOverwriteCols,mItemCnt,mOvw);
dbms_utility.COMMA_TO_TABLE(pVersionedCols,mItemCnt,mVer);
dbms_utility.COMMA_TO_TABLE(pNaturalKey||','||pVersionedCols||','||pOverwrit
eCols,mItemCnt,mAll);
mNK.DELETE(mNK.COUNT);
mOvw.DELETE(mOvw.COUNT);
mVer.DELETE(mVer.COUNT);
mAll.DELETE(mAll.COUNT);
kod('DECLARE');
kod(' CURSOR c IS');
kod(' SELECT');
formatuj_liste2(mAll,'src.{COL}',', ',75,10,'',', ',' ');
kod(' CASE');
kod(' WHEN trg.' || mNk(1) || ' IS NULL THEN ''I''');
formatuj_liste2(mVer,'(src.{COL}!=trg.{COL} OR (src.{COL} IS NULL AND trg.{C
OL} IS NOT NULL) OR (src.{COL} IS NOT NULL AND trg.{COL} IS NULL))',' OR ',250,1
,'WHEN ',' THEN ''V''',' ');
kod(' ELSE ''U''');
kod(' END oper_ind');
kod(' FROM ' || pSrcTable || ' src ');
kod(' LEFT JOIN ' || pTrgTable || ' trg ');
formatuj_liste2(mNK,'src.{COL}=trg.{COL}',' AND ',150,1,'ON ','','
');
kod(' AND trg.' || pCurrRecFlag || '=1');
kod(' WHERE trg.' || mNK(1) || ' IS NULL OR');
formatuj_liste2(mVer,'(src.{COL}!=trg.{COL} OR (src.{COL} IS NULL AND trg.{C
OL} IS NOT NULL) OR (src.{COL} IS NOT NULL AND trg.{COL} IS NULL))',' OR ',250,1
,'',' OR ',' ');
formatuj_liste2(mOvw,'(src.{COL}!=trg.{COL} OR (src.{COL} IS NULL AND trg.{C
OL} IS NOT NULL) OR (src.{COL} IS NOT NULL AND trg.{COL} IS NULL))',' OR ',250,1
,'','',' ');
kod(';');
kod('');
formatuj_liste2(mAll,'TYPE t{COL} IS TABLE OF ' || pTrgTable || '.{COL}%TYPE
INDEX BY BINARY_INTEGER;','',150,1,'','',' ');
kod(' TYPE tFlag IS TABLE OF CHAR(1) INDEX BY BINARY_INTEGER;');
kod('');
formatuj_liste2(mAll,'tr{COL} t{COL};','',150,1,'','',' ');
kod(' trOPER_IND tFlag;');
kod('');
kod(' mCurrentDate DATE;');
kod(' mHelper c%ROWTYPE;');
kod(' i BINARY_INTEGER;');
kod(' j BINARY_INTEGER;');
kod(' k BINARY_INTEGER;');
kod(' N BINARY_INTEGER;');
kod(' mTotalNewCount BINARY_INTEGER;');
kod(' mTotalOvwCount BINARY_INTEGER;');
kod(' mTotalVerCount BINARY_INTEGER;');
kod('BEGIN');
kod(' mCurrentDate := SYSDATE;');
kod(' mTotalNewCount := 0;');
kod(' mTotalVerCount := 0;');
kod(' mTotalOvwCount := 0;');
kod(' OPEN c;');
kod(' LOOP');
kod(' FETCH c BULK COLLECT INTO');
formatuj_liste2(mAll,'tr{COL},','',150,1,'','',' ');
kod(' trOPER_IND LIMIT 30000;');
kod('');
kod(' N := tr' || mAll(1) || '.COUNT;');
kod(' EXIT WHEN N=0;');
kod(' i:=1; k:=1; j:=1;');
kod('');
kod(' WHILE k<=N');
kod(' LOOP');
kod('');
kod(' WHILE i<=N AND trOPER_IND(i)=''I''');
kod(' LOOP');
kod(' i := i+1;');
kod(' END LOOP;');
kod(' IF j < i THEN j:=i; END IF;');
kod(' WHILE j<=N AND trOPER_IND(j)=''V''');
kod(' LOOP');
kod(' j := j+1;');
kod(' END LOOP;');
kod(' IF k<j THEN k:=j; END IF;');
kod('');
kod(' IF k<=N AND trOPER_IND(k)=''I'' THEN');
formatuj_liste2(mAll,'mHelper.{COL} := tr{COL}(i);','',150,1,'','','
');
kod(' mHelper.OPER_IND := trOPER_IND(i);');
kod('');
formatuj_liste2(mAll,'tr{COL}(i) := tr{COL}(k);','',150,1,'','',' ');
kod(' trOPER_IND(i) := trOPER_IND(k);');
kod('');
formatuj_liste2(mAll,'tr{COL}(k) := mHelper.{COL};','',150,1,'','','
');
kod(' trOPER_IND(k) := mHelper.OPER_IND;');
kod(' i:=i+1;');
kod(' END IF;');
kod('');
kod(' IF k<=N AND trOPER_IND(k)=''V'' THEN');
formatuj_liste2(mAll,'mHelper.{COL} := tr{COL}(j);','',150,1,'','','
');
kod(' mHelper.OPER_IND := trOPER_IND(j);');
kod('');
formatuj_liste2(mAll,'tr{COL}(j) := tr{COL}(k);','',150,1,'','',' ');
kod(' trOPER_IND(j) := trOPER_IND(k);');
kod('');
formatuj_liste2(mAll,'tr{COL}(k) := mHelper.{COL};','',150,1,'','','
');
kod(' trOPER_IND(k) := mHelper.OPER_IND;');
kod(' j:=j+1;');
kod(' END IF;');
kod('');
kod(' IF k<=N AND trOPER_IND(k)=''U'' THEN');
kod(' k:=k+1;');
kod(' END IF;');
kod(' END LOOP;');
kod(' mTotalNewCount := mTotalNewCount + i - 1;');
kod(' mTotalVerCount := mTotalVerCount + j - i;');
kod(' mTotalOvwCount := mTotalOvwCount + N - j + 1;');
kod('');
kod('');
kod(' IF i<=N THEN');
kod(' FORALL q IN i..j-1');
kod(' UPDATE ' || pTrgTable);
kod(' SET ' || pEndTS || ' = mCurrentDate, ' || pCurrRecFlag || '=0')
;
kod(' WHERE ' || pCurrRecFlag || '=1 AND');
formatuj_liste2(mNK,'{COL}=tr{COL}(q)',' AND ',150,1,'',';',' '
);
kod(' END IF;');
kod('');
kod(' IF j<=N THEN');
kod(' FORALL q IN j..N');
kod(' UPDATE ' || pTrgTable);
formatuj_liste2(mOvw,'{COL}=tr{COL}(q)',',',150,1,'SET ','',' '
);
kod(' WHERE ' || pCurrRecFlag || '=1 AND');
formatuj_liste2(mNK,'{COL}=tr{COL}(q)',' AND ',150,1,'',';',' '
);
kod(' END IF;');
kod('');
kod(' FORALL q IN 1..j-1');
kod(' INSERT INTO ' || pTrgTable);
formatuj_liste2(mAll,'{COL}',',',150,10,'(',',',' ');
kod(' ' || pSurrogateKey || ', ' || pStartTS ||', '|| pEndTS || ', '
|| pCurrRecFlag || ') VALUES (');
formatuj_liste2(mAll,'tr{COL}(q)',',',150,10,'',',',' ');
kod(' ' || pSequence || '.nextval,mCurrentDate,date''2999-12-31'',1);
');
kod('');
kod(' tr' || mAll(1) || '.DELETE;');
kod(' END LOOP;');
kod(' CLOSE c;');
kod(' COMMIT;');
kod(' :TOTAL_NEW_COUNT := mTotalNewCount;');
kod(' :TOTAL_VER_COUNT := mTotalVerCount;');
kod(' :TOTAL_OVW_COUNT := mTotalOvwCount;');
kod('END;');
execute_code;
END;
/