SET ECHO off 
REM NAME:  GENUSERDEF.SQL 
REM USAGE:"@path/genuserdef" 
REM ------------------------------------------------------------------------ 
REM REQUIREMENTS: 
REM      I have set the UTL_FILE_DIR ini the init.ora file to /tmp (on UNIX that is)
REM      This is done because all UNIX systems have this directory present and it
REM      is writable by all.
REM      IF you are going to run this on any other platform, set it to you own
REM      favourite directory and make sure that the init.ora files reflect it and
REM      that your instance is restarted with this parameter, else you will receive
REM      error messages from this script.
REM
REM WARNING -- WARNING -- WARNING -- WARNING
REM This script will currently only work on 8i versions, i.e. 8.1.x or higher
REM ------------------------------------------------------------------------ 
REM AUTHOR:  
REM    Svein Erik Brostigen, Oracle Support Services - Orlando, Fl USA
REM    Copyright 2000, Oracle Corporation      
REM ------------------------------------------------------------------------ 
REM PURPOSE: 
REM     Script to create a sql-script that will recreate the schema objects for all
REM     users except SYS and SYSTEM in the database.
REM
REM     I decided to write this script because we often have customers that have 
REM     no way of recreating their database objects or even know if anyone 
REM     have a script that will recreate the objects.
REM
REM
REM     These first version does not include partitions or some of the more esoteric 
REM     features of 8i. I hope to include these in later versions.
REM
REM     Any errors that you may find in this script, please mail me any relevant
REM     information such as: init.ora file, alert log, your environment, complete
REM     error message and any trace files.
REM     E-mail to : ebrostig@us.oracle.com
REM
REM     History:
REM             0.1     -       09/27/99        ebrostig.us
REM                     Initial version
REM
REM             0.2 -   10/09/99        ebrostig.us
REM                     Added clusters, views, triggers
REM
REM             0.3     -       10/20/99        ebrostig.us
REM                     Added sequnces
REM
REM             0.4     -       11/25/99        ebrostig.us
REM                     Added creation of users
REM ------------------------------------------------------------------------ 
REM DISCLAIMER: 
REM    This script is provided for educational purposes only. It is NOT  
REM    supported by Oracle World Wide Technical Support. 
REM    The script has been tested and appears to work as intended. 
REM    You should always run new scripts on a test instance initially. 
REM ------------------------------------------------------------------------ 
REM Main text of script follows: 


declare
        first number;
        chunk_size number :=254;
        chunk_size_returned number;
        cur_pos number:=0;
        data_chunk varchar2(254);
        stmt varchar2(1024);
        dir varchar2(1024) := '/tmp';
        file_name varchar2(1024) := 'create-schema.sql';
        
        -- Information on all users
        v_username sys.all_users.username%TYPE;

        -- Information on user accounts from dba_users
        v_user_username sys.dba_users.username%TYPE;
        v_user_password sys.dba_users.password%TYPE;
        v_user_default_tablespace sys.dba_users.default_tablespace%TYPE;
        v_user_temporary_tablespace sys.dba_users.temporary_tablespace%TYPE;
        v_user_profile sys.dba_users.profile%TYPE;
        
        -- Information on all sequences
        v_seq_sequence_name sys.all_sequences.sequence_name%TYPE;
        v_seq_min_value sys.all_sequences.min_value%TYPE;
        v_seq_max_value sys.all_sequences.max_value%TYPE;
        v_seq_increment_by sys.all_sequences.increment_by%TYPE; 
        v_seq_cycle_flag sys.all_sequences.cycle_flag%TYPE;
        v_seq_order_flag sys.all_sequences.order_flag%TYPE;
        v_seq_cache_size sys.all_sequences.cache_size%TYPE;
        v_seq_last_number sys.all_sequences.last_number%TYPE;
        
        -- Information on all clusters
        v_clus_cluster_name sys.all_clusters.cluster_name%TYPE;
        v_clus_ts sys.all_clusters.tablespace_name%TYPE;
        v_clus_pct_free sys.all_clusters.pct_free%TYPE;
        v_clus_pct_used sys.all_clusters.pct_used%TYPE;
        v_clus_key_size sys.all_clusters.key_size%TYPE;
        v_clus_ini_trans sys.all_clusters.ini_trans%TYPE;
        v_clus_max_trans sys.all_clusters.max_trans%TYPE;
        v_clus_initial_extent sys.all_clusters.initial_extent%TYPE;
        v_clus_next_extent sys.all_clusters.next_extent%TYPE;
        v_clus_min_extents sys.all_clusters.min_extents%TYPE;
        v_clus_max_extents sys.all_clusters.max_extents%TYPE;
        v_clus_pct_increase sys.all_clusters.pct_increase%TYPE;
        v_clus_freelists sys.all_clusters.freelists%TYPE;
        v_clus_freelist_groups sys.all_clusters.freelist_groups%TYPE;
        v_clus_cluster_type sys.all_clusters.cluster_type%TYPE;
        v_clus_function sys.all_clusters.function%TYPE;
        v_clus_hashkeys sys.all_clusters.hashkeys%TYPE;
        v_clus_degree sys.all_clusters.degree%TYPE;
        v_clus_cache sys.all_clusters.cache%TYPE;
        v_clus_single_table sys.all_clusters.single_table%TYPE;
        
        -- Information on all cluster hash expressions
        v_clh_hash_expression sys.all_cluster_hash_expressions.hash_expression%TYPE;
        
        
        -- Information on all tables
        v_owner sys.all_tables.owner%TYPE;
        v_table_name sys.all_tables.table_name%TYPE;
        v_tablespace_name sys.all_tables.tablespace_name%TYPE;
        v_initial_extent sys.all_tables.initial_extent%TYPE;
        v_next_extent sys.all_tables.next_extent%TYPE;
        v_pct_increase sys.all_tables.pct_increase%TYPE;
        v_cluster_name sys.all_tables.cluster_name%TYPE;
        v_degree sys.all_tables.degree%TYPE;
        v_min_extents sys.all_tables.min_extents%TYPE;
        v_max_extents sys.all_tables.max_extents%TYPE;
        v_freelists sys.all_tables.freelists%TYPE;
        v_freelist_groups sys.all_tables.freelist_groups%TYPE;
        v_ini_trans sys.all_tables.ini_trans%TYPE;
        v_max_trans sys.all_tables.max_trans%TYPE;
        
        
        -- Information on columns
        v_column_name sys.all_tab_columns.column_name%TYPE;
        v_data_type sys.all_tab_columns.data_type%TYPE;
        v_data_length sys.all_tab_columns.data_length%TYPE;
        v_nullable sys.all_tab_columns.nullable%TYPE;
        v_data_precision sys.all_tab_columns.data_precision%TYPE;
        
        -- Information triggers
        v_trigger_name sys.all_triggers.trigger_name%TYPE;
        v_trigger_type sys.all_triggers.trigger_type%TYPE;
        v_triggering_event sys.all_triggers.triggering_event%TYPE;
        v_table_owner sys.all_triggers.table_owner%TYPE;
        v_trigtab_name sys.all_triggers.table_name%TYPE;
        v_when_clause sys.all_triggers.when_clause%TYPE;
        v_status sys.all_triggers.status%TYPE;
        v_description sys.all_triggers.description%TYPE;
        v_trigger_body sys.all_triggers.trigger_body%TYPE;
        
        -- Information on constraints
        v_constraint_name sys.all_constraints.constraint_name%TYPE;
        v_constraint_type sys.all_constraints.constraint_type%TYPE;
        v_cons_status sys.all_constraints.status%TYPE;
        
        -- Information on constraint columns
        v_cons_column sys.all_cons_columns.column_name%TYPE;
        
        -- Information on views
        v_view_name sys.all_views.view_name%TYPE;
        v_text sys.all_views.text%TYPE;
        
        
        

        outfile utl_file.file_type;
        
        cursor c_dba_users is
        select username, password, default_tablespace, temporary_tablespace, profile from sys.dba_users where username=v_username;
        
        cursor c_user is
        select username from all_users where username != 'SYS' and username != 'SYSTEM';

        cursor c_sequence is
        select sequence_name, min_value, max_value, increment_by, cycle_flag, order_flag, cache_size, last_number
        from sys.all_sequences where sequence_owner=v_username;
        
        cursor c_cluster is
        select cluster_name, tablespace_name, pct_free, pct_used, key_size, ini_trans, max_trans, initial_extent,
        next_extent, min_extents, max_extents, pct_increase, freelists, freelist_groups, cluster_type, function,
        hashkeys, degree, cache, single_table from sys.all_clusters where owner=v_username;
        
        cursor c_tables is
        select owner, table_name, tablespace_name, initial_extent, next_extent, pct_increase, degree  from sys.all_tables
        where owner=v_username;

        cursor c_columns is
        select column_name, data_type, data_length, nullable, data_precision from sys.all_tab_columns where table_name=v_table_name and owner = v_owner;
        
        cursor c_triggers is
        select trigger_name, trigger_type, triggering_event, table_owner, table_name, when_clause, status,
        description, trigger_body from all_triggers where table_name=v_table_name and owner = v_owner;
        
        cursor c_constraints is
        select constraint_name, constraint_type, status from sys.all_constraints where table_name = v_table_name and owner
        = v_owner;
        
        cursor c_cons_columns is
        select column_name from sys.all_cons_columns where constraint_name = v_constraint_name and owner =
        v_owner order by position;
        
        cursor c_views is
        select view_name, text from sys.all_views where owner = v_owner order by view_name;
        
        
 PROCEDURE dump_body(trigger_name IN VARCHAR2, stmt IN varchar2)
  IS
    data_chunk          VARCHAR2(254);  -- these can go higher
    chunk_size          NUMBER:=254;    -- up to 32k
    chunk_size_returned NUMBER;
    mycursor            INTEGER; 
    cur_pos             NUMBER:=0;
    rows                NUMBER;
    dummy               NUMBER;
        status              VARCHAR2(50);
        tmpfile                         utl_file.file_type;
  BEGIN

     tmpfile := utl_file.fopen(dir, file_name, 'a', 32767);
     mycursor:=dbms_sql.open_cursor;
     dbms_sql.parse(mycursor, stmt, dbms_sql.v7);
     dbms_sql.bind_variable(mycursor, ':trigger_name', trigger_name);

     dbms_sql.define_column_long(mycursor,1);
     dummy:=dbms_sql.execute(mycursor);
     rows:=dbms_sql.fetch_rows(mycursor);
     loop
         -- fetch 'chunks' of the long until we have got the lot
         dbms_sql.column_value_long(mycursor,
                                  1,
                                  chunk_size,
                                  cur_pos,
                                  data_chunk,
                                  chunk_size_returned);
         utl_file.put(tmpfile, data_chunk); -- use PUT to preserve data
         cur_pos:=cur_pos + chunk_size;
         exit when chunk_size_returned = 0; 
     end loop;
     dbms_sql.close_cursor(mycursor);
         utl_file.fflush(tmpfile);
         utl_file.fclose(tmpfile);
  EXCEPTION
        when utl_file.invalid_path then
                raise_application_error(-20100, 'Invalid path in dump_body');
        when utl_file.invalid_mode then
                raise_application_error(-20101, 'Invalid mode in dump_body');
        when utl_file.invalid_operation then
                raise_application_error(-20102, 'Invalid operation in dump_body');
        when utl_file.invalid_filehandle then
                raise_application_error(-20103, 'Invalid filehandle in dump_body');
        when utl_file.write_error then
                raise_application_error(-20104, 'Write error in dump_body');
        when utl_file.read_error then
                raise_application_error(-20105, 'Read error in dump_body');
        when utl_file.internal_error then
                raise_application_error(-20106, 'Internal error in dump_body');
    WHEN OTHERS THEN
                raise_application_error(-20107, 'Other Error in dump_body');
  END dump_body;
        

-- Begin the main loop...
begin
        outfile := utl_file.fopen(dir, file_name, 'w');
        utl_file.putf(outfile, '-- Create schema objects script\n--\n-- Version 0.4 11/25/1999\n-- Copyright (c) 1999 Oracle Corp., USA\n-- Written by: ebrostig@us.oracle.com\n\n');
        utl_file.putf(outfile, 'Created on %s\n', sysdate);
        utl_file.putf(outfile, '\n-- Create all the non system users first...\n');
        open c_user;
        loop
                fetch c_user into v_username;
                exit when c_user%NOTFOUND;
        
                open c_dba_users;
                loop
                        fetch c_dba_users into v_user_username, v_user_password, v_user_default_tablespace, v_user_temporary_tablespace, v_user_profile;
                        exit when c_dba_users%NOTFOUND;

                        utl_file.putf(outfile, 'CREATE USER %s IDENTIFIED BY VALUES ''%s'' ',v_user_username, v_user_password);
                        utl_file.putf(outfile, 'DEFAULT TABLESPACE %s TEMPORARY TABLESPACE %s ', v_user_default_tablespace, v_user_temporary_tablespace);
                        utl_file.putf(outfile, 'PROFILE %s;\n', v_user_profile);
                end loop;
                close c_dba_users;
        end loop;
        close c_user;
        utl_file.putf(outfile, '\n-- Finished creating all non-system users...\n');

        open c_user;
        loop
                fetch c_user into v_username;
                exit when c_user%NOTFOUND;

                -- Lets create the sequences, drop them first and creat them afterwards.
                -- ?? Should last_number be set as a min_value when the sequences is recreated? Option?
                
                open c_sequence;
                loop
                        fetch c_sequence into v_seq_sequence_name, v_seq_min_value, v_seq_max_value, v_seq_increment_by,
                        v_seq_cycle_flag, v_seq_order_flag, v_seq_cache_size, v_seq_last_number;
                        exit when c_sequence%NOTFOUND;
                        
                        utl_file.putf(outfile, '\n-- Drop sequence first...\n');
                        utl_file.putf(outfile, 'DROP SEQUENCE %s.%s;\n', v_username, v_seq_sequence_name);
                        utl_file.putf(outfile, '\n-- Create statement for sequence %s.%s\n\n', v_username,
                        v_seq_sequence_name);
                        utl_file.putf(outfile, 'CREATE SEQUENCE %s.%s\n', v_username, v_seq_sequence_name);
                        utl_file.putf(outfile, 'INCREMENT BY %s\n', v_seq_increment_by);
                        utl_file.putf(outfile, 'MINVALUE %s\n', v_seq_min_value);
                        utl_file.putf(outfile, 'MAXVALUE %s\n', v_seq_max_value);
                        if v_seq_cycle_flag = 'Y' then
                                utl_file.putf(outfile, 'CYCLE\n');
                        else
                                utl_file.putf(outfile, 'NOCYCLE\n');
                        end if;
                        if v_seq_order_flag = 'Y' then
                                utl_file.putf(outfile, 'ORDER\n');
                        else
                                utl_file.putf(outfile, 'NOORDER\n');
                        end if;
                        if v_seq_cache_size = 0 then
                                utl_file.putf(outfile, 'NOCACHE;\n');
                        else
                                utl_file.putf(outfile, 'CACHE %s;\n', v_seq_cache_size);
                        end if;
                end loop;
                close c_sequence;
                
                -- Drop and recreate the clusters. Needs to be done before any tables are created.
                
                open c_cluster;
                loop
                        fetch c_cluster into v_clus_cluster_name, v_clus_ts, v_clus_pct_free, v_clus_pct_used,
                        v_clus_key_size, v_clus_ini_trans, v_clus_max_trans, v_clus_initial_extent, v_clus_next_extent,
                        v_clus_min_extents, v_clus_max_extents, v_clus_pct_increase, v_clus_freelists,
                        v_clus_freelist_groups, v_clus_cluster_type, v_clus_function, v_clus_hashkeys, v_clus_degree,
                        v_clus_cache, v_clus_single_table;
                        exit when c_cluster%NOTFOUND;
                        utl_file.putf(outfile, '\n-- Drop cluster cascade first...\n');
                        utl_file.putf(outfile, 'DROP CLUSTER %s.%s CASCADE CONSTRAINTS;\n', v_owner, v_clus_cluster_name);
                        utl_file.putf(outfile, '\n-- Create statement for cluster %s.%s\n\n', v_owner, v_clus_cluster_name); 
                        utl_file.putf(outfile, 'CREATE CLUSTER %s.%s (', v_owner, v_clus_cluster_name);
                        open c_columns;
                        first := 1;
                        loop
                                fetch c_columns into v_column_name, v_data_type, v_data_length, v_nullable, v_data_precision;
                                exit when c_columns%NOTFOUND;   
                                if first = 1 then
                                        if v_data_type = 'CHAR' or v_data_type = 'VARCHAR2'  or v_data_type = 'NCHAR' or v_data_type = 'NVARCHAR2' or v_data_type = 'RAW' or v_data_type = 'UROWID' then
                                                utl_file.putf(outfile, '\n%s %s(%s)', v_column_name, v_data_type,v_data_length);
                                        elsif v_data_type = 'NUMBER' then
                                                if v_data_precision != '' then
                                                        utl_file.putf(outfile, '\n%s %s(%s,%s)', v_column_name, v_data_type,v_data_length,v_data_precision);
                                                else
                                                        utl_file.putf(outfile, '\n%s %s(%s)', v_column_name, v_data_type,v_data_length);
                                                end if;

                                        else
                                                utl_file.putf(outfile, '\n%s %s', v_column_name, v_data_type);
                                        end if;
                                        first := 0;
                                else 
                                        if v_data_type = 'CHAR' or v_data_type = 'VARCHAR2'  or v_data_type = 'NCHAR' or v_data_type = 'NVARCHAR2' or v_data_type = 'RAW' or v_data_type = 'UROWID' then
                                                utl_file.putf(outfile, ',\n%s %s(%s)', v_column_name, v_data_type,v_data_length);
                                        elsif v_data_type = 'NUMBER' then
                                                if v_data_precision != '' then
                                                        utl_file.putf(outfile, ',\n%s %s(%s,%s)', v_column_name, v_data_type,v_data_length,v_data_precision);
                                                else
                                                        utl_file.putf(outfile, ',\n%s %s(%s)', v_column_name, v_data_type,v_data_length);
                                                end if;
                                        else
                                                utl_file.putf(outfile, ',\n%s %s', v_column_name, v_data_type);
                                        end if;
                                end if;
                                if v_nullable = 'N' then
                                        utl_file.putf(outfile, ' NOT NULL');
                                end if;
                        end loop;
                        close c_columns;
                        utl_file.putf(outfile, ')\n');
                        if v_clus_key_size > 0 then
                                utl_file.putf(outfile, 'SIZE %s ', v_clus_key_size);
                        end if;
                        if v_clus_hashkeys > 0 and v_clus_single_table = 'Y'  then
                                utl_file.putf(outfile, 'SINGLE TABLE HASHKEYS %s ', v_clus_hashkeys);
                        elsif v_clus_hashkeys > 0 and v_clus_single_table = 'N' then
                                utl_file.putf(outfile, 'HASHKEYS %s ', v_clus_hashkeys);
                                if v_clus_function != 'NULL' then
                                        utl_file.putf(outfile, 'HASH IS %s\n', v_clus_function);
                                end if;
                        end if;
                        utl_file.putf(outfile, 'STORAGE (INITIAL %s ', v_clus_initial_extent);
                        utl_file.putf(outfile, ' NEXT %s PCT_INCREASE %s', v_clus_next_extent,v_clus_pct_increase);
                        utl_file.put(outfile, ') TABLESPACE ');
                        utl_file.put(outfile, v_clus_ts);
                        if LTRIM(RTRIM(v_clus_degree)) != '1' and LTRIM(RTRIM(v_clus_degree)) != 'DEFAULT' then
                                utl_file.putf(outfile, ' PARALLEL %s', LTRIM(RTRIM(v_clus_degree)));
                        end if;
                end loop;
                close c_cluster;
                         
                
                open c_tables;
                loop
                        fetch c_tables into  v_owner, v_table_name, v_tablespace_name, v_initial_extent,
                        v_next_extent,v_pct_increase, v_degree;
        
                        exit when c_tables%NOTFOUND;
                        utl_file.putf(outfile, '\n-- Drop table cascade first...\n');
                        utl_file.putf(outfile, 'DROP TABLE %s.%s CASCADE CONSTRAINTS;\n', v_owner, v_table_name);
                        utl_file.putf(outfile,'\n-- Create statement for table %s.%s\n\n', v_owner, v_table_name);
                        utl_file.put(outfile, 'CREATE TABLE ');
                        utl_file.put(outfile, v_owner);
                        utl_file.put(outfile, '.');
                        utl_file.put(outfile, v_table_name);
                        utl_file.put(outfile, ' ( ');
                        open c_columns;
                        first := 1;
                        loop
                                fetch c_columns into v_column_name, v_data_type, v_data_length, v_nullable, v_data_precision;
                                exit when c_columns%NOTFOUND;   
                                if first = 1 then
                                        if v_data_type = 'CHAR' or v_data_type = 'VARCHAR2'  or v_data_type = 'NCHAR' or v_data_type = 'NVARCHAR2' or v_data_type = 'RAW' or v_data_type = 'UROWID' then
                                                utl_file.putf(outfile, '\n%s %s(%s)', v_column_name, v_data_type,v_data_length);
                                        elsif v_data_type = 'NUMBER' then
                                                if v_data_precision != '' then
                                                        utl_file.putf(outfile, '\n%s %s(%s,%s)', v_column_name, v_data_type,v_data_length,v_data_precision);
                                                else
                                                        utl_file.putf(outfile, '\n%s %s(%s)', v_column_name, v_data_type,v_data_length);
                                                end if;

                                        else
                                                utl_file.putf(outfile, '\n%s %s', v_column_name, v_data_type);
                                        end if;
                                        first := 0;
                                else 
                                        if v_data_type = 'CHAR' or v_data_type = 'VARCHAR2'  or v_data_type = 'NCHAR' or v_data_type = 'NVARCHAR2' or v_data_type = 'RAW' or v_data_type = 'UROWID' then
                                                utl_file.putf(outfile, ',\n%s %s(%s)', v_column_name, v_data_type,v_data_length);
                                        elsif v_data_type = 'NUMBER' then
                                                if v_data_precision != '' then
                                                        utl_file.putf(outfile, ',\n%s %s(%s,%s)', v_column_name, v_data_type,v_data_length,v_data_precision);
                                                else
                                                        utl_file.putf(outfile, ',\n%s %s(%s)', v_column_name, v_data_type,v_data_length);
                                                end if;
                                        else
                                                utl_file.putf(outfile, ',\n%s %s', v_column_name, v_data_type);
                                        end if;
                                end if;
                                if v_nullable = 'N' then
                                        utl_file.putf(outfile, ' NOT NULL');
                                end if;
                        end loop;
                        close c_columns;
                        utl_file.putf(outfile, ')\n STORAGE (INITIAL %s ', v_initial_extent);
                        utl_file.putf(outfile, ' NEXT %s PCT_INCREASE %s', v_next_extent,v_pct_increase);
                        utl_file.put(outfile, ') TABLESPACE ');
                        utl_file.put(outfile, v_tablespace_name);
                        if LTRIM(RTRIM(v_degree)) != '1' and LTRIM(RTRIM(v_degree)) != 'DEFAULT' then
                                utl_file.putf(outfile, ' PARALLEL %s', LTRIM(RTRIM(v_degree)));
                        end if;
                        utl_file.put(outfile, ';');
                        utl_file.new_line(outfile);
                        utl_file.fflush(outfile);
        
-- Now create triggers for the table...
                        utl_file.putf(outfile,'\n-- Creating triggers for table %s.%s\n\n', v_owner, v_table_name);
                        stmt:='SELECT TRIGGER_BODY FROM SYS.ALL_TRIGGERS WHERE TRIGGER_NAME = :trigger_name';
                        open c_triggers;
                        loop
                                fetch c_triggers into v_trigger_name, v_trigger_type, v_triggering_event, v_table_owner,
                                v_trigtab_name, v_when_clause, v_status, v_description, v_trigger_body;
                                exit when c_triggers%NOTFOUND;
                                utl_file.putf(outfile,'CREATE OR REPLACE TRIGGER %s.%s %s ', v_table_owner, v_trigger_name,
                                v_trigger_type);
                                utl_file.putf(outfile, '%s ON %s.%s\n', v_triggering_event, v_table_owner, v_trigtab_name);
                                utl_file.putf(outfile, 'WHEN %s\n', v_when_clause);
                                utl_file.fclose(outfile);
                                dump_body(v_trigger_name, stmt);
                                outfile := utl_file.fopen(dir, file_name,'a');
                                utl_file.putf(outfile, '\nEND;\n');                     
                                utl_file.fflush(outfile);
                        end loop;               
                        close c_triggers;
                
-- Now create primary keys and indexes...
                        utl_file.putf(outfile,'\n-- Creating constraints for table %s.%s\n\n', v_owner, v_table_name);
                        open c_constraints;
                        loop
                                fetch c_constraints into v_constraint_name, v_constraint_type, v_cons_status;
                                exit when c_constraints%NOTFOUND;
-- Primary Key Constraint
                                if v_constraint_type = 'P' then  
                                        utl_file.putf(outfile, 'ALTER TABLE %s ADD PRIMARY KEY (', v_table_name);
                                        first := 1;
                                        open c_cons_columns;
                                        loop
                                                fetch c_cons_columns into v_cons_column;
                                                exit when c_cons_columns%NOTFOUND;
                                                if first = 1 then
                                                        utl_file.putf(outfile, '%s', v_cons_column);
                                                        first := 0;
                                                else
                                                        utl_file.putf(outfile, ',%s', v_cons_column);
                                                end if;
                                        end loop;
                                        close c_cons_columns;
                                        utl_file.putf(outfile, ') %s;\n\n', v_cons_status);
                                elsif v_constraint_type = 'U' then  -- Unique Key Constraint
                                        utl_file.putf(outfile, 'ALTER TABLE %s ADD CONSTRAINT %s\nUNIQUE (', v_table_name, v_constraint_name);
                                        first := 1;
                                        open c_cons_columns;
                                        loop
                                                fetch c_cons_columns into v_cons_column;
                                                exit when c_cons_columns%NOTFOUND;
                                                if first = 1 then
                                                        utl_file.putf(outfile, '%s', v_cons_column);
                                                        first := 0;
                                                else
                                                        utl_file.putf(outfile, ',%s', v_cons_column);
                                                end if;
                                        end loop;
                                        close c_cons_columns;
                                        utl_file.putf(outfile, ');\n\n');
                                end if;
                        
                        end loop;
                        close c_constraints;                    
                end loop;
                close c_tables;

-- Create views
                utl_file.putf(outfile,'\n-- Creating views for user %s\n\n', v_owner);
                stmt := 'SELECT TEXT FROM SYS.ALL_VIEWS WHERE VIEW_NAME =:trigger_name';
                open c_views;
                loop
                        fetch c_views into v_view_name, v_text;
                        exit when c_views%NOTFOUND;
                        utl_file.putf(outfile, 'CREATE OR REPLACE VIEW %s\nAS ', v_view_name);
                        utl_file.fflush(outfile);
                        utl_file.fclose(outfile);
                        dump_body(v_view_name, stmt);
                        outfile := utl_file.fopen(dir, file_name,'a');
                        utl_file.putf(outfile, ';\n\n');
                end loop;
                close c_views;          
                
        end loop;
        utl_file.fclose(outfile);
        
end;
 
/
