LogicalSchema sql script

--------------------------------------------------------------------------------
-- logicalschema.sql 
-- 1. Set initial preferences for the logicalschema instance
-- 2.Install clean-up procedure for logical schemas
-- 3.Install init and done procedure for logical schema
--------------------------------------------------------------------------------
-- Input parameter:
--  N/A
--------------------------------------------------------------------------------
-- Usage:
-- Save the script as sql file logicalschema.sql
-- C:\> sqlplus dbauser/password[@TNS_name]
-- SQL> @[<Path\>]logicalschema.sql
--------------------------------------------------------------------------------
-- Notice:
--------------------------------------------------------------------------------
-- my company
-- Author: eureka
--------------------------------------------------------------------------------
-- History:
-- Who When     What
-- --- -------- ----------------------------------------------------------------
-- eureka  10.23.2013 --  add standard header
--------------------------------------------------------------------------------

WHENEVER SQLERROR EXIT
declare 
tbname varchar(255);
begin 
SELECT tablespace_name into tbname FROM dba_tablespaces where tablespace_name=upper('&mytablespace');
if ( tbname is  null)
  then
raise_application_error (-20000,'the space is not in the database:' || chr(10)|| dbms_utility.format_error_stack);
  end if;
 exception
  when no_data_found then 
  raise_application_error (-20001,'Error in select tablespace:' || chr(10)|| dbms_utility.format_error_stack); 
  when others then 
  raise_application_error (-20002,'Error in select tablespace:' || chr(10)|| dbms_utility.format_error_stack); 
end;
/

declare 
exportflag varchar(255);
dcname varchar(255);
begin 
exportflag:='&myexportflag';
if ( exportflag='TRUE' )
  then
SELECT directory_name into dcname FROM dba_directories where directory_name = upper('&myOracleDirectory');
 end if;
    exception
  when no_data_found then 
  raise_application_error (-20001,'the directory name is not in the database:' || chr(10)|| dbms_utility.format_error_stack); 
  when others then 
  raise_application_error (-20002,'the directory name is not in the database:' || chr(10)|| dbms_utility.format_error_stack); 
end;
/

declare
l_dml VARCHAR2(32767);
begin
l_dml :='CREATE USER &myschemaowner IDENTIFIED BY &mypass DEFAULT TABLESPACE &mytablespace QUOTA UNLIMITED ON &mytablespace';
EXECUTE IMMEDIATE  l_dml;
end;
/

declare
e_exit_table exception;
pragma exception_init(e_exit_table, -00955);
l_dml VARCHAR2(32767);
begin
l_dml := 'create  table &myschemaowner.LookUpTable (schemaname varchar(100), sourcename varchar(100), tablename varchar(30), createtime date, primary key(schemaname,sourcename))';
EXECUTE IMMEDIATE l_dml;
exception 
when e_exit_table then  null;
when others then 
 raise_application_error (-20000,'Error in create table:' || chr(10)|| dbms_utility.format_error_stack);                     
end;
/

declare
e_exit_sequence exception;
pragma exception_init(e_exit_sequence, -00955);
l_dml VARCHAR2(32767);
begin
l_dml:= 'CREATE SEQUENCE  &myschemaowner.SEQMYCACHE  MINVALUE 1 MAXVALUE 9999999 INCREMENT BY 1 START WITH 1 NOCACHE  NOORDER  CYCLE';
EXECUTE IMMEDIATE l_dml;
exception 
when e_exit_sequence then  null;
when others then 
 raise_application_error (-20000,'Error in create sequence:' || chr(10)|| dbms_utility.format_error_stack);                    
end;
/

declare
l_dml VARCHAR2(32767);
begin
l_dml :='grant  create session  to &myschemaowner';
EXECUTE IMMEDIATE  l_dml;
l_dml :='grant  create table  to &myschemaowner';
EXECUTE IMMEDIATE  l_dml;
l_dml :='grant  connect, resource  to &myschemaowner';
EXECUTE IMMEDIATE  l_dml;
l_dml :='grant select  any dictionary to &myschemaowner';
EXECUTE IMMEDIATE  l_dml;
l_dml := 'create or replace type  &myschemaowner.ints as table of number(10,0)';
EXECUTE IMMEDIATE  l_dml;
end;
/

declare 
exportflag varchar(255);
dcname varchar(255);
begin 
exportflag:='&myexportflag';
if ( exportflag='TRUE' )
  then
EXECUTE IMMEDIATE 'GRANT read, write ON DIRECTORY &myOracleDirectory TO &myschemaowner';
 end if;
    exception
  when no_data_found then 
  raise_application_error (-20001,'the directory name is not in the database:' || chr(10)|| dbms_utility.format_error_stack); 
  when others then 
  raise_application_error (-20002,'the directory name is not in the database:' || chr(10)|| dbms_utility.format_error_stack); 
end;
/

create or replace PACKAGE         &myschemaowner.my$imp_util IS

  PROCEDURE cleanup(sch_prefix_in   IN VARCHAR2 := 'MY$',
                    sch_name_in     IN VARCHAR2,
                    lo_threshold_in IN INTEGER,
                    hi_threshold_in IN INTEGER,
                    backup_in       IN BOOLEAN,
                    cleanup_in      IN BOOLEAN,
                    dir_in     IN VARCHAR2,
                    tsmaxsize        IN INTEGER,
                    status_out      OUT VARCHAR2);

  PROCEDURE expdp_schema(sch_in      IN VARCHAR2,
                         dir_in     IN VARCHAR2,
                         res_out     OUT VARCHAR2,
                         success_out OUT BOOLEAN);

  PROCEDURE impdp_schema(dmpfile_in IN VARCHAR2,
                         dir_in     IN VARCHAR2,
                         status_out OUT VARCHAR2);

END my$imp_util;
/

create or replace PACKAGE BODY          &myschemaowner.my$imp_util
IS
  TYPE bytes_per_schema_rt IS record(
     v_user  LookUpTable.schemaname%TYPE
    ,v_bytes user_segments.bytes%TYPE
  );

  TYPE bps_tt IS TABLE OF bytes_per_schema_rt
    INDEX BY PLS_INTEGER;

  --------------------------------------------------
  -- Private constant declarations
  --------------------------------------------------

  --------------------------------------------------
  -- Private function and procedure implementations
  --------------------------------------------------

  PROCEDURE to_scr (msg_in IN VARCHAR2)
  IS
  BEGIN
    dbms_output.put_line(msg_in);
  END;

  PROCEDURE stripline
  IS
  BEGIN
    to_scr (lpad('=', 50, '='));
  END;

  FUNCTION bytes_used

    RETURN INTEGER
  IS
    retval INTEGER;
  BEGIN
    SELECT SUM(bytes)
      INTO retval
      FROM user_segments;
    RETURN retval;
  END;

  FUNCTION pct_used (bytes_in IN INTEGER, c_max_bytes IN INTEGER)
    RETURN INTEGER
  IS
  BEGIN
    RETURN round((bytes_in / c_max_bytes) * 100);
  END;

  PROCEDURE load_bps_tab (
    usr_like_in IN VARCHAR2
   ,bps_tab_out OUT NOCOPY bps_tt
  )
  IS
  BEGIN
select lp.schemaname, SUM(nvl(us.bytes, 0))
BULK COLLECT INTO bps_tab_out
from user_segments us, LookUpTable lp
where us.segment_name = lp.tablename 
group by lp.schemaname
order by min(lp.createtime);  
  END; 
  
  
  PROCEDURE drop_table (table_in IN VARCHAR2)
  IS
 table_not_exist EXCEPTION;
 PRAGMA EXCEPTION_INIT(table_not_exist, -00942);
  BEGIN
    EXECUTE IMMEDIATE
      'DROP table '||table_in||' cascade constraints';
  EXCEPTION
  when table_not_exist then  return;
    WHEN OTHERS THEN
      raise_application_error (-20000,
                               'Error in DROP_TABLE:' || chr(10)
                            || dbms_utility.format_error_stack);
  END;
  

  PROCEDURE drop_user (user_in IN VARCHAR2)
  IS
  BEGIN
for mytablename in (select table_name from user_tables ut, LookUpTable lp where ut.table_name = lp.tablename and lp.schemaname =user_in and  ut.table_name != 'LOOKUPTABLE')
loop
drop_table(mytablename.table_name);
end loop;
  EXCEPTION
    WHEN OTHERS
    THEN
      raise_application_error (-20000,
                               'Error in DROP_USER:' || chr(10)
                            || dbms_utility.format_error_stack);
  END;


  FUNCTION remove_last_cr (txt_in IN VARCHAR2)
    RETURN VARCHAR2
  IS
    l_txt VARCHAR2(32767) := txt_in;
  BEGIN
    WHILE substr(l_txt, -1, 1) = chr(10)
    LOOP
      l_txt := substr(l_txt, 1, length(l_txt) - 1);
    END LOOP;
        
    RETURN l_txt;
  END;

  PROCEDURE cleanup_internal (
    schema_like_in  IN VARCHAR2
   ,lo_threshold_in IN INTEGER
   ,hi_threshold_in IN INTEGER
   ,savefile_in IN  BOOLEAN
   ,c_max_bytes        IN INTEGER
   ,dir_in        IN VARCHAR2
   ,int_status_out  OUT VARCHAR2
   
  )
  IS
    l_usr_like         VARCHAR2(30) := upper(schema_like_in);
    l_min_pct          INTEGER := lo_threshold_in;
    l_max_pct          INTEGER := hi_threshold_in;
    l_used_bytes       INTEGER := bytes_used;
    l_used_bytes_start INTEGER;
    l_bps_tab          bps_tt;
    l_idx              PLS_INTEGER;
    l_success            BOOLEAN := TRUE;
    l_status   VARCHAR2(32767);
  BEGIN
    l_used_bytes_start := l_used_bytes;

    IF l_max_pct <= pct_used (l_used_bytes,c_max_bytes)
    THEN
      load_bps_tab (l_usr_like, l_bps_tab);
    
      l_idx := l_bps_tab.FIRST;
      LOOP
        EXIT WHEN(l_min_pct >= pct_used (l_used_bytes,c_max_bytes)) OR (l_idx IS NULL);

        l_used_bytes := l_used_bytes - l_bps_tab(l_idx).v_bytes;
        
        IF savefile_in 
        THEN
          expdp_schema (sch_in => l_bps_tab(l_idx).v_user
                   ,dir_in  => dir_in
                       ,res_out => l_status
                   ,success_out => l_success);
         END IF;
        if l_success 
        then
        drop_user (l_bps_tab(l_idx).v_user);
        else
           int_status_out := l_status;
           return;
        end if;

        l_idx := l_bps_tab.NEXT(l_idx);
      END LOOP;
    END IF;

    int_status_out := 'L3Cache storage used[MB]/free[MB]/cleaned[MB]: '
                   || round(l_used_bytes / 1024 / 1024) || '/'
                   || round((c_max_bytes - l_used_bytes) / 1024 / 1024) || '/'
                   || round((l_used_bytes_start - l_used_bytes) / 1024 / 1024);
  EXCEPTION
    WHEN OTHERS
    THEN
      int_status_out := 'Exception in CLEANUP_INTERNAL:' || chr(10)
                     || dbms_utility.format_error_stack;
  END;
  

  --------------------------------------------------
  -- Public function and procedure implementations
  --------------------------------------------------
  PROCEDURE cleanup (
    sch_prefix_in   IN VARCHAR2 := 'MY$'
   ,sch_name_in     IN VARCHAR2
   ,lo_threshold_in IN INTEGER 
   ,hi_threshold_in IN INTEGER
   ,backup_in       IN BOOLEAN 
   ,cleanup_in      IN BOOLEAN 
   ,dir_in          IN VARCHAR2
   ,tsmaxsize        IN INTEGER
   ,status_out      OUT VARCHAR2
  )
  IS
    l_usr_like VARCHAR2(30) := CASE substr(sch_prefix_in, -1, 1)
                                 WHEN '%' THEN upper(sch_prefix_in)
                                 ELSE upper(sch_prefix_in) || '%'
                               END;
    l_status   VARCHAR2(32767);
  BEGIN
    
    IF cleanup_in
    THEN
    cleanup_internal (
      schema_like_in  => l_usr_like
     ,lo_threshold_in => lo_threshold_in
     ,hi_threshold_in => hi_threshold_in
     ,savefile_in => backup_in
     ,c_max_bytes => tsmaxsize
     ,dir_in => dir_in 
     ,int_status_out  => l_status
    );
     status_out := status_out
                 || chr(10)
                 || remove_last_cr (l_status);
    END IF;
END;

PROCEDURE expdp_schema(sch_in      IN VARCHAR2,
                        dir_in     IN VARCHAR2,
                         res_out     OUT VARCHAR2,
                         success_out OUT BOOLEAN) is
    l_dt_stmp  VARCHAR2(30) := to_char(SYSDATE, 'YYMMDDHH24MISS');
    l_exp_job  VARCHAR2(30) := 'my$EXPDP_JOB_' || l_dt_stmp;
    l_dmp_file VARCHAR2(100) := upper(sch_in) || '_' || l_dt_stmp || '.DMP';
    l_log_file VARCHAR2(100) := upper(sch_in) || '_' || l_dt_stmp ||
                                '_EXP.LOG';
  
    l_handle       NUMBER;
    l_job_state    VARCHAR2(30);
    l_log_entry    ku$_logentry;
    l_status_entry ku$_jobstatus;
    l_status       ku$_status;
    l_idx          PLS_INTEGER;
    l_file         VARCHAR2(100);
    l_table_list   VARCHAR2(2000);
    l_subquery     VARCHAR2(200);
  BEGIN
  
    for mytablename in (select table_name
                          from user_tables ut, LookUpTable lp
                         where ut.table_name = lp.tablename
                           and lp.schemaname = sch_in
                           and ut.table_name != 'LOOKUPTABLE')
    
     loop
      if l_table_list is null then
        l_table_list := '''' || mytablename.table_name;
      else
        l_table_list := l_table_list || ''',''' || mytablename.table_name;
      end if;
     end loop;
     
    if l_table_list is not null then
      l_table_list := l_table_list || ''',''LOOKUPTABLE''';
    
      l_subquery := 'WHERE SCHEMANAME=''' || sch_in || '''';
    
      l_handle := dbms_datapump.open(operation => 'EXPORT',
                                     job_mode  => 'TABLE',
                                     job_name  => l_exp_job);
    
      dbms_datapump.add_file(handle    => l_handle,
                             filename  => l_dmp_file,
                             directory => dir_in);
    
      dbms_datapump.add_file(handle    => l_handle,
                             filename  => l_log_file,
                             filetype  => dbms_datapump.ku$_file_type_log_file,
                             directory => dir_in);
    
      dbms_datapump.metadata_filter(handle      => l_handle,
                                    NAME        => 'NAME_LIST',
                                    VALUE       => l_table_list,
                                    object_type => 'TABLE');
    
      DBMS_DATAPUMP.DATA_FILTER(handle     => l_handle,
                                NAME       => 'SUBQUERY',
                                value      => l_subquery,
                                table_name => 'LOOKUPTABLE');
    
      IF (bitand(l_status.mask, dbms_datapump.ku$_status_job_status) != 0) THEN
        l_status_entry := l_status.job_status;
      
        IF l_status_entry IS NOT NULL THEN
          l_idx := l_status_entry.files.FIRST;
          IF l_idx IS NOT NULL THEN
            l_file := l_status_entry.files(l_idx).file_name;
          END IF;
        END IF;
      END IF;
    
      dbms_datapump.start_job(l_handle);
    
      dbms_datapump.wait_for_job(handle    => l_handle,
                                 job_state => l_job_state);
    
      dbms_datapump.detach(l_handle);
    
      IF l_job_state = 'COMPLETED' THEN
        success_out := TRUE;
        res_out     := 'data export successfully completed' || chr(10);
      ELSE
        res_out := 'data export: final job state = ' || l_job_state ||
                   chr(10);
      END IF;
    
      IF l_file IS NOT NULL THEN
        res_out := res_out || 'Dump-File: ' || l_file;
      END IF;
    
      res_out := remove_last_cr(res_out);
    
    else
    
      res_out := 'No table found for the logical schema!' || chr(10);
    end if;
  EXCEPTION
    WHEN OTHERS THEN
      success_out := FALSE;
      res_out := 'Exception in data export:' || chr(10);
    
      l_status := dbms_datapump.get_status(l_handle,
                                           dbms_datapump.ku$_status_job_error);
    
      IF (bitand(l_status.mask, dbms_datapump.ku$_status_job_error) != 0) THEN
        l_log_entry := l_status.error;
      
        IF l_log_entry IS NOT NULL THEN
          l_idx := l_log_entry.FIRST;
          WHILE l_idx IS NOT NULL LOOP
            res_out := res_out || l_log_entry(l_idx).logtext;
          
            IF l_idx != l_log_entry.LAST THEN
              res_out := res_out || chr(10);
            END IF;
          
            l_idx := l_log_entry.NEXT(l_idx);
          END LOOP;
        END IF;
      ELSE
        res_out := res_out || dbms_utility.format_error_stack;
      END IF;
    
      dbms_datapump.detach(l_handle);
      res_out := remove_last_cr(res_out);
    
  end expdp_schema;

  PROCEDURE impdp_schema(dmpfile_in IN VARCHAR2, 
                         dir_in     IN VARCHAR2, 
                         status_out OUT VARCHAR2) IS
    l_dt_stmp         VARCHAR2(30) := to_char(SYSDATE, 'YYMMDDHH24MISS');
    l_imp_job         VARCHAR2(30) := 'MY$IMPDP_JOB_' || l_dt_stmp;
    l_log_file        VARCHAR2(100) := upper(substr(dmpfile_in,
                                                    1,
                                                    length(dmpfile_in) - 4)) ||
                                       '_IMP.LOG';
    l_log_lookup_file VARCHAR2(100) := upper(substr(dmpfile_in,
                                                    1,
                                                    length(dmpfile_in) - 4)) ||
                                       '_LOOKUP_IMP.LOG';
  
    l_handle    NUMBER;
    l_job_state VARCHAR2(30);
    l_log_entry ku$_logentry;
    l_status    ku$_status;
    l_idx       PLS_INTEGER;
  BEGIN
  
    --import business data
    l_handle := dbms_datapump.open(operation => 'IMPORT',
                                   job_mode  => 'TABLE',
                                   job_name  => l_imp_job);
  
    dbms_datapump.add_file(handle    => l_handle,
                           filename  => dmpfile_in,
                           directory => dir_in);
  
    dbms_datapump.add_file(handle    => l_handle,
                           filename  => l_log_file,
                           filetype  => dbms_datapump.ku$_file_type_log_file,
                           directory => dir_in);
  
    dbms_datapump.start_job(l_handle);
  
    dbms_datapump.wait_for_job(handle    => l_handle,
                               job_state => l_job_state);
  
    dbms_datapump.detach(l_handle);
  
    --import lookuptable records
    l_handle := dbms_datapump.open(operation => 'IMPORT',
                                   job_mode  => 'TABLE',
                                   job_name  => l_imp_job || '_lookup');
    DBMS_DATAPUMP.metadata_filter(handle => l_handle,
                                  name   => 'NAME_EXPR',
                                  VALUE  => 'IN(''LOOKUPTABLE'')');
  
    dbms_datapump.add_file(handle    => l_handle,
                           filename  => dmpfile_in,
                           directory => dir_in);
  
    dbms_datapump.add_file(handle    => l_handle,
                           filename  => l_log_lookup_file,
                           filetype  => dbms_datapump.ku$_file_type_log_file,
                           directory => dir_in);
  
    dbms_datapump.set_parameter(handle => l_handle,
                                name   => 'TABLE_EXISTS_ACTION',
                                value  => 'APPEND');
    dbms_datapump.start_job(l_handle);
  
    dbms_datapump.wait_for_job(handle    => l_handle,
                               job_state => l_job_state);
  
    dbms_datapump.detach(l_handle);
  
    IF l_job_state = 'COMPLETED' THEN
      status_out := 'data import successfully completed';
    ELSE
      status_out := 'data import: final job state = ' || l_job_state;
    END IF;
  EXCEPTION
    WHEN OTHERS THEN
      status_out := 'Exception in data import:' || chr(10);
    
      l_status := dbms_datapump.get_status(l_handle,
                                           dbms_datapump.ku$_status_job_error);
    
      IF (bitand(l_status.mask, dbms_datapump.ku$_status_job_error) != 0) THEN
        l_log_entry := l_status.error;
      
        IF l_log_entry IS NOT NULL THEN
          l_idx := l_log_entry.FIRST;
          WHILE l_idx IS NOT NULL LOOP
            status_out := status_out || l_log_entry(l_idx).logtext;
          
            IF l_idx != l_log_entry.LAST THEN
              status_out := status_out || chr(10);
            END IF;
          
            l_idx := l_log_entry.NEXT(l_idx);
          END LOOP;
        END IF;
      ELSE
        status_out := status_out || dbms_utility.format_error_stack;
      END IF;
    
      dbms_datapump.detach(l_handle);
      status_out := remove_last_cr(status_out);
  END impdp_schema;

END my$imp_util;
/


CREATE OR REPLACE PROCEDURE &myschemaowner.my$initschema (
  user_in IN VARCHAR2
,res_out OUT VARCHAR2
)
IS
  l_status VARCHAR2(32767);
BEGIN

res_out := res_out || l_status;
END;
/

create or replace PROCEDURE &myschemaowner.my$doneschema (
user_in IN VARCHAR2,
lo_threshold_in IN INTEGER,
hi_threshold_in IN INTEGER,
auto_cleanup IN BOOLEAN := TRUE,
export IN BOOLEAN := FALSE,
file_path IN VARCHAR2,
tablespacemaxsize IN INTEGER,
res_out OUT VARCHAR2
)
IS
l_dml VARCHAR2(32767);
BEGIN
my$imp_util.cleanup(
                sch_name_in => user_in
                ,lo_threshold_in => lo_threshold_in 
                ,hi_threshold_in => hi_threshold_in
                ,backup_in   => export 
                ,cleanup_in  => auto_cleanup
                ,dir_in =>  file_path
                ,tsmaxsize => tablespacemaxsize
                ,status_out  => res_out );
l_dml := 'delete from LookUpTable where tablename not in ( select table_name from user_tables )';
execute immediate l_dml;
commit;
EXECUTE IMMEDIATE 'PURGE RECYCLEBIN'; 
END;
/

 

posted on 2013-11-12 19:27  子虚乌有  阅读(206)  评论(0编辑  收藏  举报