Monday 11 March 2013

PLSQL backup time...

PL SQL package backup tutorial

I started this project because i needed program that will easily back up my files from developer without clicking on package and exporting it to save my work...
Second i wrote it because there is Bug in SQL DEVELOPER that causes lines to be messed up  when you have large code...
Example:

You have large code and export it with right click on package name and select save specs and body

Real code is written like this...

1 line - BEGIN
2 LINE - SELECT RTRIM(SUBSTR(INSTANCE_NAME,1,8))||'-'||RTRIM(SUBSTR(HOST_NAME,1,15))
3 line - INTO L_INPUTNAME
4 line - FROM V$INSTANCE ;
5 line - EXCEPTION WHEN OTHERS THEN
6 LINE - NULL;
7 line - END;

but sometimes export does the weird thing and saves it messed up
switching the line order....
1 line - BEGIN
2 line - SELECT RTRIM(SUBSTR(INSTANCE_NAME,1,8))||'-'||RTRIM(SUBSTR(HOST_NAME,1,15))
4 line - FROM V$INSTANCE ;
3 line - INTO L_INPUTNAME
5 line - EXCEPTION WHEN OTHERS THEN
6 line - NULL;
7 line - END;

I googled this program somewhere on the web two years ago and manage to rewrite it for my needs...
So without any chit chat let's see the code

CREATE OR REPLACE
PROCEDURE BACKUP_OF_PL_FILES
    (I_TIPE_OF_OBJECT    VARCHAR2
    ,I_NAME_OF_OBJECT    VARCHAR2 DEFAULT '%')
IS
    PL_OUTPUT    UTL_FILE.FILE_TYPE;
    L_READ UTL_FILE.FILE_TYPE;
    L_BUFFER    VARCHAR2(4000);
    G_SESSONID    VARCHAR2(80);
    L_LINE        VARCHAR2(80);
    L_COUNTER        NUMBER(30) :=1 ;
    L_SAVE VARCHAR2(32767);
    L_INPUTNAME    VARCHAR2(20);
    L_ERRNUM    NUMBER := 0;
    L_DIRNAME VARCHAR2(100) := ' ';
BEGIN
  
   G_SESSONID := USERENV('sessionid');
   L_DIRNAME := 'BACKUP_PL/'||I_NAME_OF_OBJECT||'/'||TO_CHAR(TO_DATE(SYSDATE,'dd.mm.yy'),'yyyymmdd')||'/';
   -----------------------------------------------------------------------------
  
    BEGIN
        SELECT    RTRIM(SUBSTR(INSTANCE_NAME,1,8))||'-'||RTRIM(SUBSTR(HOST_NAME,1,15))
        INTO    L_INPUTNAME
        FROM    V$INSTANCE ;
    EXCEPTION WHEN OTHERS THEN
        NULL;
    END;

    IF I_NAME_OF_OBJECT='%' THEN
        G_SESSONID    := 'BAK_'||INITCAP(I_TIPE_OF_OBJECT)||'_'||L_INPUTNAME||'_'||TO_CHAR(SYSDATE, 'DDMMYY_HH24MI') || '.pls';
    ELSE
        G_SESSONID    := 'BAK_'||INITCAP(I_NAME_OF_OBJECT)||'_'||L_INPUTNAME||'_'||TO_CHAR(SYSDATE, 'DDMMYY_HH24MI') || '.pls';
    END IF;   
  
   PL_OUTPUT := UTL_FILE.FOPEN('c:\BACKUP', G_SESSONID,'A',4000);      
   UTL_FILE.PUT_LINE(PL_OUTPUT, 'c:\BACKUP' || L_DIRNAME || G_SESSONID);

    FOR RS_TYPE IN (SELECT    DISTINCT TYPE, NAME
            FROM    USER_SOURCE
            WHERE    TYPE LIKE UPPER(I_TIPE_OF_OBJECT)||'%'
            AND    NAME LIKE UPPER(I_NAME_OF_OBJECT)
            ORDER BY 2,1 )
    LOOP
        FOR RS_NAME IN (SELECT    TEXT
                FROM    USER_SOURCE
                WHERE    TYPE = RS_TYPE.TYPE
                AND    NAME = RS_TYPE.NAME )
        LOOP
            BEGIN
                IF (L_COUNTER = 1 OR UPPER(RS_NAME.TEXT) LIKE '%PACKAGE BODY%') THEN
                    L_BUFFER := 'CREATE OR REPLACE '||RS_NAME.TEXT ;
                ELSE
                    L_BUFFER := RTRIM(RS_NAME.TEXT,' ');
                END IF;
                IF SUBSTR(L_BUFFER,-1,1) = ';' THEN
                    UTL_FILE.PUT_LINE(PL_OUTPUT,RTRIM(L_BUFFER));
                ELSE
                    UTL_FILE.PUT_LINE(PL_OUTPUT,RTRIM(L_BUFFER,SUBSTR(L_BUFFER,-1,1)));
                END IF;
                L_COUNTER := L_COUNTER + 1 ;
           
            EXCEPTION WHEN OTHERS THEN
                L_ERRNUM :=1 ;
                DBMS_OUTPUT.PUT_LINE('error 2nd loop...'||SQLERRM);
            END ;
        END LOOP;
        L_COUNTER := 1;
        UTL_FILE.PUT_LINE(PL_OUTPUT,'/');              
        IF RS_TYPE.TYPE NOT LIKE '%PACKAGE%' OR RS_TYPE.TYPE LIKE '%PACKAGE BODY%' THEN
          UTL_FILE.PUT_LINE(PL_OUTPUT,L_LINE);   
        END IF;
    END LOOP;
    UTL_FILE.FCLOSE(PL_OUTPUT);
   L_READ := UTL_FILE.FOPEN('PL_OUT', G_SESSONID,'A',4000);
   ----------------------
EXCEPTION WHEN OTHERS THEN
    DBMS_OUTPUT.PUT_LINE('Error... '||SQLCODE);
    UTL_FILE.FCLOSE(PL_OUTPUT);
END BACKUP_OF_PL_FILES;

 
Basically this procedure is searching database same as export and write package in your local directory c:\BACKUP

Calling is easy. All you have to do is call it from anonymous block with specification(package,procedure,function...) and name of the Package/Procedure... like this

BEGIN
   BACKUP_OF_PL_FILES('package','MY_PACKAGE_NAME_PKG');
   BACKUP_OF_PL_FILES('package','MY_PACKAGE_NAME_PKG');
   BACKUP_OF_PL_FILES('procedure','MY_PROCEDURE_NAME);
   BACKUP_OF_PL_FILES('function','MY_FUNCTION_NAME');
END;





0 comments:

Post a Comment