You are on page 1of 5

CREATE OR REPLACE PROCEDURE update_scd(

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;
/

You might also like