Saturday, September 30, 2023

How to restore a table or schema from past using FLASHBACK database future. Remember not FLASHBACK table which relies on UNDO.

How to restore a table or schema from past using FLASHBACK database future. Remember not FLASHBACK table which relies on UNDO.


Situation:

We may need a table as it existed in the past as part of the below operation demand...


1. USER MISTAKE: Incorrect user input and the table in production is in bad state, so we need to go back in the past to retrieve the proper content and correct user mistake

2. ROOT CAUSE ANALYSIS: Application might have legitimate interest to look back in time to see what was value of a record as in the past

3. Application upgrade failure, DDL on the table to be reverted back



Solution: 


Using Oracle FLASHBACK feature of oracle..

A. We can go back to past timestamp from current timestamp

B. Retrieve our data

C. Rollforward to the current timestamp


Prereqs:

1. You need Flashback enabled or Guranteed restore point created to go back into a particular time.

2. Archivelog mode should be ON and all the archivelogs from past timestamp until the current timestamp should be available.


Steps)

1. Verify if prereqs are met?


Command:

alter session set nls_date_format='DD/MON/YYYY HH24:MI:SS';

set lines 300

set pages 3000

set colsep ,

select name,open_mode,database_role,db_unique_name,name,flashback_on,log_mode,force_logging from v$database;

select scn,GUARANTEE_FLASHBACK_DATABASE,NAME from V$RESTORE_POINT;

select sequence#,status,completion_time,first_change#,next_change# from v$archived_log order by 1;


Actual output:


SQL> alter session set nls_date_format='DD/MON/YYYY HH24:MI:SS';


Session altered.


SQL> set lines 300

set pages 3000

set colsep ,SQL> SQL>

SQL> select name,open_mode,database_role,db_unique_name,name,flashback_on,log_mode,force_logging from v$database;


NAME     ,OPEN_MODE           ,DATABASE_ROLE   ,DB_UNIQUE_NAME                ,NAME     ,FLASHBACK_ON      ,LOG_MODE    ,FORCE_LOGGING

---------,--------------------,----------------,------------------------------,---------,------------------,------------,---------------------------------------

GGTGT04T ,READ WRITE          ,PRIMARY         ,GGTGT04T                      ,GGTGT04T ,RESTORE POINT ONLY,ARCHIVELOG  ,YES


SQL> select scn,GUARANTEE_FLASHBACK_DATABASE,NAME from V$RESTORE_POINT;


       SCN,GUA,NAME

----------,---,--------------------------------------------------------------------------------------------------------------------------------

   1032103,YES,PRE_GGREPLICAT


SQL> select sequence#,status,completion_time,first_change#,next_change# from v$archived_log order by 1;


 SEQUENCE#,S,COMPLETION_TIME     ,FIRST_CHANGE#,NEXT_CHANGE#

----------,-,--------------------,-------------,------------

         1,A,30/SEP/2023 09:29:32,      1017565,     1093405


SQL> select * from v$log;


    GROUP#,   THREAD#, SEQUENCE#,     BYTES, BLOCKSIZE,   MEMBERS,ARC,STATUS          ,FIRST_CHANGE#,FIRST_TIME          ,NEXT_CHANGE#,NEXT_TIME     ,    CON_ID

----------,----------,----------,----------,----------,----------,---,----------------,-------------,--------------------,------------,--------------------,----------

         1,         1,         1, 209715200,       512,         1,YES,INACTIVE        ,      1017565,26/AUG/2023 21:44:36,     1093405,30/SEP/2023 09:29:30,           0

         2,         1,         2, 209715200,       512,         1,NO ,CURRENT         ,      1093405,30/SEP/2023 09:29:30,  1.8447E+19,              ,         0

         3,         1,         0, 209715200,       512,         1,YES,UNUSED          ,            0,                    ,     0,                    ,         0


SQL>





2. Flashback the database to PRE_GGREPLICAT (go to past)


shu immediate;

startup mount;

flashback database to PRE_GGREPLICAT;

set lines 300

set pages 3000

set colsep ,

select name,open_mode,database_role,db_unique_name,name,flashback_on,log_mode,force_logging from v$database;


Actual output:


SQL> shu immediate;

startup mount;

Database closed.

Database dismounted.

ORACLE instance shut down.

SQL>

ORACLE instance started.


Total System Global Area,3221222464,bytes

Fixed Size              ,   8901696,bytes

Variable Size           ,1107296256,bytes

Database Buffers        ,2097152000,bytes

Redo Buffers            ,   7872512,bytes

Database mounted.

SQL> SQL>

SQL> select name,open_mode,database_role,db_unique_name,name,flashback_on,log_mode,force_logging from v$database;


NAME     ,OPEN_MODE           ,DATABASE_ROLE   ,DB_UNIQUE_NAME                ,NAME     ,FLASHBACK_ON      ,LOG_MODE    ,FORCE_LOGGING

---------,--------------------,----------------,------------------------------,---------,------------------,------------,---------------------------------------

GGTGT04T ,MOUNTED             ,PRIMARY         ,GGTGT04T                      ,GGTGT04T ,RESTORE POINT ONLY,ARCHIVELOG  ,YES


SQL>


SQL> flashback database to restore point PRE_GGREPLICAT;


Flashback complete.


SQL> select name,open_mode,database_role,db_unique_name,name,flashback_on,log_mode,force_logging from v$database;


NAME     ,OPEN_MODE           ,DATABASE_ROLE   ,DB_UNIQUE_NAME                ,NAME     ,FLASHBACK_ON      ,LOG_MODE    ,FORCE_LOGGING

---------,--------------------,----------------,------------------------------,---------,------------------,------------,---------------------------------------

GGTGT04T ,MOUNTED             ,PRIMARY         ,GGTGT04T                      ,GGTGT04T ,RESTORE POINT ONLY,ARCHIVELOG  ,YES


SQL> select name,open_mode,checkpoint_change#,controlfile_change# from v$database;


NAME     ,OPEN_MODE           ,CHECKPOINT_CHANGE#,CONTROLFILE_CHANGE#

---------,--------------------,------------------,-------------------

GGTGT04T ,MOUNTED             ,           1118165,            1032104


SQL> select distinct(checkpoint_change#) from v$datafile;


CHECKPOINT_CHANGE#

------------------

           1032104


SQL>




2. Open the DB in read only mode


alter database open read only;


set lines 300

set pages 3000

set colsep ,

select name,open_mode,database_role,db_unique_name,name,flashback_on,log_mode,force_logging from v$database;


Actual output:


SQL> alter database open read only;


Database altered.


SQL> select name,open_mode,database_role,db_unique_name,name,flashback_on,log_mode,force_logging from v$database;


NAME     ,OPEN_MODE           ,DATABASE_ROLE   ,DB_UNIQUE_NAME                ,NAME     ,FLASHBACK_ON      ,LOG_MODE    ,FORCE_LOGGING

---------,--------------------,----------------,------------------------------,---------,------------------,------------,---------------------------------------

GGTGT04T ,READ ONLY           ,PRIMARY         ,GGTGT04T                      ,GGTGT04T ,RESTORE POINT ONLY,ARCHIVELOG  ,YES


SQL> select parameter,value from v$option where upper(parameter) like '%VAULT%';


PARAMETER                                                       ,VALUE

----------------------------------------------------------------,----------------------------------------------------------------

Oracle Database Vault                                           ,TRUE


SQL>





Note before flashback I had vault disabled, but after flashback it came alive. Since my db had vault activated always.


3. Export the schema ENCVAULT_TEST


exp OWNER=ENCVAULT_TEST buffer=100000 file=/tmp/encvault_test_preflashback1.dmp log=/tmp/encvault_test_preflashback1.log


>>> it will fail because we have TDE enabled.


Actual output:


[oracle@vcentos79-oracle-ggtgt ~]$ exp OWNER=ENCVAULT_TEST buffer=100000 file=/tmp/encvault_test_preflashback1.dmp log=/tmp/encvault_test_preflashback1.log


Export: Release 19.0.0.0.0 - Production on Sat Sep 30 14:41:19 2023

Version 19.3.0.0.0


Copyright (c) 1982, 2019, Oracle and/or its affiliates.  All rights reserved.



Username: / as sysdba


Connected to: Oracle Database 19c Enterprise Edition Release 19.0.0.0.0 - Production

Version 19.3.0.0.0

Export done in US7ASCII character set and AL16UTF16 NCHAR character set

server uses AL32UTF8 character set (possible charset conversion)


About to export specified users ...

. exporting pre-schema procedural objects and actions

...

. exporting cluster definitions

. about to export ENCVAULT_TEST's tables via Conventional Path ...

EXP-00111: Table ENCRYPT_TAB1 resides in an Encrypted Tablespace ENCRYPT_TS1 and will not be exported

. exporting synonyms

. exporting views

...

Export terminated successfully with warnings.

[oracle@vcentos79-oracle-ggtgt ~]$



4. If step 3 fails, export the data as csv using the pl/sql proc


variable p_sql varchar2(1000);

variable p_dir varchar2(1000);

variable p_file varchar2(2000);


exec :p_sql:='select * from ENCVAULT_TEST.ENCRYPT_TAB1';

exec :p_dir:='DATA_PUMP_DIR';

exec :p_file:='30Sep2023_actual_ENCRYPT_TAB1.csv';


exec :p_sql:='select * from ENCVAULT_TEST.GGTEST1';

exec :p_file:='30Sep2023_actual_GGTEST1.csv';


col :p_sql for a45

col :p_dir for a20

col :p_file for a45

select :p_sql,:p_dir,:p_file from dual;


declare

  v_finaltxt  VARCHAR2(4000);

  v_v_val     VARCHAR2(4000);

  v_n_val     NUMBER;

  v_d_val     DATE;

  v_ret       NUMBER;

  c           NUMBER;

  d           NUMBER;

  col_cnt     INTEGER;

  f           BOOLEAN;

  rec_tab     DBMS_SQL.DESC_TAB;

  col_num     NUMBER;

  v_fh        UTL_FILE.FILE_TYPE;

BEGIN

  c := DBMS_SQL.OPEN_CURSOR;

  DBMS_SQL.PARSE(c, :p_sql, DBMS_SQL.NATIVE);

  d := DBMS_SQL.EXECUTE(c);

  DBMS_SQL.DESCRIBE_COLUMNS(c, col_cnt, rec_tab);

  FOR j in 1..col_cnt

  LOOP

    CASE rec_tab(j).col_type

      WHEN 1 THEN DBMS_SQL.DEFINE_COLUMN(c,j,v_v_val,2000);

      WHEN 2 THEN DBMS_SQL.DEFINE_COLUMN(c,j,v_n_val);

      WHEN 12 THEN DBMS_SQL.DEFINE_COLUMN(c,j,v_d_val);

    ELSE

      DBMS_SQL.DEFINE_COLUMN(c,j,v_v_val,2000);

    END CASE;

  END LOOP;

  -- This part outputs the HEADER

  v_fh := UTL_FILE.FOPEN(upper(:p_dir),:p_file,'w',32767);

  FOR j in 1..col_cnt

  LOOP

    v_finaltxt := ltrim(v_finaltxt||','||lower(rec_tab(j).col_name),',');

  END LOOP;

  UTL_FILE.PUT_LINE(v_fh, v_finaltxt);

  -- This part outputs the DATA

  LOOP

    v_ret := DBMS_SQL.FETCH_ROWS(c);

    EXIT WHEN v_ret = 0;

    v_finaltxt := NULL;

    FOR j in 1..col_cnt

    LOOP

      CASE rec_tab(j).col_type

        WHEN 1 THEN DBMS_SQL.COLUMN_VALUE(c,j,v_v_val);

                    v_finaltxt := ltrim(v_finaltxt||',"'||v_v_val||'"',',');

        WHEN 2 THEN DBMS_SQL.COLUMN_VALUE(c,j,v_n_val);

                    v_finaltxt := ltrim(v_finaltxt||','||v_n_val,',');

        WHEN 12 THEN DBMS_SQL.COLUMN_VALUE(c,j,v_d_val);

                    v_finaltxt := ltrim(v_finaltxt||','||to_char(v_d_val,'DD/MM/YYYY HH24:MI:SS'),',');

      ELSE

        DBMS_SQL.COLUMN_VALUE(c,j,v_v_val);

        v_finaltxt := ltrim(v_finaltxt||',"'||v_v_val||'"',',');

      END CASE;

    END LOOP;

  --  DBMS_OUTPUT.PUT_LINE(v_finaltxt);

    UTL_FILE.PUT_LINE(v_fh, v_finaltxt);

  END LOOP;

  UTL_FILE.FCLOSE(v_fh);

  DBMS_SQL.CLOSE_CURSOR(c);

END;

/


Actual output:


SQL> variable p_sql varchar2(1000);

variable p_dir varchar2(1000);

variable p_file varchar2(2000);


exec :p_sql:='select * from ENCVAULT_TEST.ENCRYPT_TAB1';

exec :p_dir:='DATA_PUMP_DIR';

exec :p_file:='30Sep2023_actual_ENCRYPT_TAB1.csv';SQL> SQL> SQL> SQL>

PL/SQL procedure successfully completed.


SQL>

PL/SQL procedure successfully completed.


SQL>


PL/SQL procedure successfully completed.


SQL> col :p_sql for a45

col :p_dir for a20

col :p_file for a30

select :p_sql,:p_dir,:p_file from dual;SQL> SQL> SQL>


:P_SQL                                       ,:P_DIR              ,:P_FILE

---------------------------------------------,--------------------,------------------------------

select * from ENCVAULT_TEST.ENCRYPT_TAB1     ,DATA_PUMP_DIR       ,30Sep2023_actual_ENCRYPT_TAB1.

                                             ,                    ,csv



SQL> col :p_file for a75

SQL> /


:P_SQL                                       ,:P_DIR              ,:P_FILE

---------------------------------------------,--------------------,---------------------------------------------------------------------------

select * from ENCVAULT_TEST.ENCRYPT_TAB1     ,DATA_PUMP_DIR       ,30Sep2023_actual_ENCRYPT_TAB1.csv


SQL> declare

  v_finaltxt  VARCHAR2(4000);

  v_v_val     VARCHAR2(4000);

  v_n_val     NUMBER;

  v_d_val     DATE;

  v_ret       NUMBER;

  c           NUMBER;

  d           NUMBER;

  col_cnt     INTEGER;

  f           BOOLEAN;

  rec_tab     DBMS_SQL.DESC_TAB;

  col_num     NUMBER;

  v_fh        UTL_FILE.FILE_TYPE;

BEGIN

  2    3    4    5    6    7    8    9   10   11   12   13   14   15    c := DBMS_SQL.OPEN_CURSOR;

  DBMS_SQL.PARSE(c, :p_sql, DBMS_SQL.NATIVE);

  d := DBMS_SQL.EXECUTE(c);

  DBMS_SQL.DESCRIBE_COLUMNS(c, col_cnt, rec_tab);

  FOR j in 1..col_cnt

  LOOP

    CASE rec_tab(j).col_type

      WHEN 1 THEN DBMS_SQL.DEFINE_COLUMN(c,j,v_v_val,2000);

      WHEN 2 THEN DBMS_SQL.DEFINE_COLUMN(c,j,v_n_val);

      WHEN 12 THEN DBMS_SQL.DEFINE_COLUMN(c,j,v_d_val);

    ELSE

      DBMS_SQL.DEFINE_COLUMN(c,j,v_v_val,2000);

    END CASE;

  END LOOP;

  -- This part outputs the HEADER

  v_fh := UTL_FILE.FOPEN(upper(:p_dir),:p_file,'w',32767);

  FOR j in 1..col_cnt

  LOOP

    v_finaltxt := ltrim(v_finaltxt||','||lower(rec_tab(j).col_name),',');

  END LOOP;

  UTL_FILE.PUT_LINE(v_fh, v_finaltxt);

  -- This part outputs the DATA

  LOOP

    v_ret := DBMS_SQL.FETCH_ROWS(c);

    EXIT WHEN v_ret = 0;

    v_finaltxt := NULL;

    FOR j in 1..col_cnt

    LOOP

      CASE rec_tab(j).col_type

        WHEN 1 THEN DBMS_SQL.COLUMN_VALUE(c,j,v_v_val);

                    v_finaltxt := ltrim(v_finaltxt||',"'||v_v_val||'"',',');

        WHEN 2 THEN DBMS_SQL.COLUMN_VALUE(c,j,v_n_val);

                    v_finaltxt := ltrim(v_finaltxt||','||v_n_val,',');

        WHEN 12 THEN DBMS_SQL.COLUMN_VALUE(c,j,v_d_val);

                    v_finaltxt := ltrim(v_finaltxt||','||to_char(v_d_val,'DD/MM/YYYY HH24:MI:SS'),',');

      ELSE

        DBMS_SQL.COLUMN_VALUE(c,j,v_v_val);

        v_finaltxt := ltrim(v_finaltxt||',"'||v_v_val||'"',',');

      END CASE;

 16   17   18   19   20   21   22   23   24   25   26   27   28   29   30   31   32   33   34   35   36   37   38   39   40   41   42   43   44   45   46   47   48   49   50   51   52   53   54      END LOOP;

  --  DBMS_OUTPUT.PUT_LINE(v_finaltxt);

    UTL_FILE.PUT_LINE(v_fh, v_finaltxt);

 55   56   57    END LOOP;

  UTL_FILE.FCLOSE(v_fh);

 58   59    DBMS_SQL.CLOSE_CURSOR(c);

END;

 60   61  /

declare

*

ERROR at line 1:

ORA-01031: insufficient privileges

ORA-06512: at "SYS.DBMS_SQL", line 1721

ORA-06512: at line 17



SQL>



4b. If step 4 fails use the below to dump the data to csv from sqlplus


set trims on

set trim on

set lines 1200

set headsep off

set pagesize 0

set trimspool on

set serveroutput on

spool C:\vagrant\ENCRYPT_TAB1_AT2.csv


variable p_sql varchar2(1000);


exec :p_sql:='select * from ENCVAULT_TEST.ENCRYPT_TAB1';


declare

  v_finaltxt  VARCHAR2(4000);

  v_v_val     VARCHAR2(4000);

  v_n_val     NUMBER;

  v_d_val     DATE;

  v_ret       NUMBER;

  c           NUMBER;

  d           NUMBER;

  col_cnt     INTEGER;

  f           BOOLEAN;

  rec_tab     DBMS_SQL.DESC_TAB;

  col_num     NUMBER;

  v_fh        UTL_FILE.FILE_TYPE;

BEGIN

  c := DBMS_SQL.OPEN_CURSOR;

  DBMS_SQL.PARSE(c, :p_sql, DBMS_SQL.NATIVE);

  d := DBMS_SQL.EXECUTE(c);

  DBMS_SQL.DESCRIBE_COLUMNS(c, col_cnt, rec_tab);

  FOR j in 1..col_cnt

  LOOP

    CASE rec_tab(j).col_type

      WHEN 1 THEN DBMS_SQL.DEFINE_COLUMN(c,j,v_v_val,2000);

      WHEN 2 THEN DBMS_SQL.DEFINE_COLUMN(c,j,v_n_val);

      WHEN 12 THEN DBMS_SQL.DEFINE_COLUMN(c,j,v_d_val);

    ELSE

      DBMS_SQL.DEFINE_COLUMN(c,j,v_v_val,2000);

    END CASE;

  END LOOP;

  -- This part outputs the HEADER

  -- v_fh := UTL_FILE.FOPEN(upper(:p_dir),:p_file,'w',32767);

  FOR j in 1..col_cnt

  LOOP

    v_finaltxt := ltrim(v_finaltxt||','||lower(rec_tab(j).col_name),',');

  END LOOP;

  -- UTL_FILE.PUT_LINE(v_fh, v_finaltxt);

  dbms_output.put_line(v_finaltxt);

  -- This part outputs the DATA

  LOOP

    v_ret := DBMS_SQL.FETCH_ROWS(c);

    EXIT WHEN v_ret = 0;

    v_finaltxt := NULL;

    FOR j in 1..col_cnt

    LOOP

      CASE rec_tab(j).col_type

        WHEN 1 THEN DBMS_SQL.COLUMN_VALUE(c,j,v_v_val);

                    v_finaltxt := ltrim(v_finaltxt||','||v_v_val||'',',');

        WHEN 2 THEN DBMS_SQL.COLUMN_VALUE(c,j,v_n_val);

                    v_finaltxt := ltrim(v_finaltxt||','||v_n_val,',');

        WHEN 12 THEN DBMS_SQL.COLUMN_VALUE(c,j,v_d_val);

                    v_finaltxt := ltrim(v_finaltxt||','||to_char(v_d_val,'DD/MM/YYYY HH24:MI:SS'),',');

      ELSE

        DBMS_SQL.COLUMN_VALUE(c,j,v_v_val);

        v_finaltxt := ltrim(v_finaltxt||','||v_v_val||'',',');

      END CASE;

    END LOOP;

  --  DBMS_OUTPUT.PUT_LINE(v_finaltxt);

  -- UTL_FILE.PUT_LINE(v_fh, v_finaltxt);

  dbms_output.put_line(v_finaltxt);

  END LOOP;

  -- UTL_FILE.FCLOSE(v_fh);

  DBMS_SQL.CLOSE_CURSOR(c);

END;

/


spool off


Actual output:


Info collected to CSV. Just trimmed down the query and header info from the output and copied the row data alone to the actual db server for next step.


>done


5. Mount the db back


shu immediate;

startup mount;

set lines 300

set pages 3000

set colsep ,

select name,open_mode,database_role,db_unique_name,name,flashback_on,log_mode,force_logging,checkpoint_change#,controlfile_change# from v$database;

select * from v$log;


Actual output:


SQL> shu immediate;

Database closed.

Database dismounted.

ORACLE instance shut down.

SQL> 

SQL> startup mount;

ORACLE instance started.


Total System Global Area 3221222464 bytes

Fixed Size     8901696 bytes

Variable Size 1107296256 bytes

Database Buffers 2097152000 bytes

Redo Buffers     7872512 bytes

Database mounted.

SQL> set lines 300

set pages 3000

set colsep ,SQL> SQL> 

SQL> select name,open_mode,database_role,db_unique_name,name,flashback_on,log_mode,force_logging,checkpoint_change#,controlfile_change# from v$database;


NAME ,OPEN_MODE       ,DATABASE_ROLE   ,DB_UNIQUE_NAME       ,NAME ,FLASHBACK_ON   ,LOG_MODE ,FORCE_LOGGING ,CHECKPOINT_CHANGE#,CONTROLFILE_CHANGE#

---------,--------------------,----------------,------------------------------,---------,------------------,------------,---------------------------------------,------------------,-------------------

GGTGT04T ,MOUNTED       ,PRIMARY       ,GGTGT04T       ,GGTGT04T ,RESTORE POINT ONLY,ARCHIVELOG ,YES ,     1118165, 1032104


SQL> select * from v$log;


    GROUP#,   THREAD#, SEQUENCE#,     BYTES, BLOCKSIZE,   MEMBERS,ARC,STATUS       ,FIRST_CHANGE#,FIRST_TIM,NEXT_CHANGE#,NEXT_TIME,   CON_ID

----------,----------,----------,----------,----------,----------,---,----------------,-------------,---------,------------,---------,----------

1,     1,       1, 209715200,   512, 1,YES,INACTIVE       ,      1017565,26-AUG-23,     1093405,30-SEP-23,       0

3,     1,       0, 209715200,   512, 1,YES,UNUSED       ,   0,       ,   0,     ,       0

2,     1,       2, 209715200,   512, 1,NO ,CURRENT       ,      1093405,30-SEP-23,  1.8447E+19,     ,       0


SQL>



6. Recover the db back to its original point in time (current timestamp)


recover database;

alter database open;


Actual output:


SQL> recover database;

Media recovery complete.

SQL> select name,open_mode,database_role,db_unique_name,name,flashback_on,log_mode,force_logging,checkpoint_change#,controlfile_change# from v$database;


NAME ,OPEN_MODE       ,DATABASE_ROLE   ,DB_UNIQUE_NAME       ,NAME ,FLASHBACK_ON   ,LOG_MODE ,FORCE_LOGGING ,CHECKPOINT_CHANGE#,CONTROLFILE_CHANGE#

---------,--------------------,----------------,------------------------------,---------,------------------,------------,---------------------------------------,------------------,-------------------

GGTGT04T ,MOUNTED       ,PRIMARY       ,GGTGT04T       ,GGTGT04T ,RESTORE POINT ONLY,ARCHIVELOG ,YES ,     1118165, 1032104


SQL> select distinct(checkppi  oint_change#) from vR $datafile;


CHECKPOINT_CHANGE#

------------------

  1118163


SQL> alter database open;


Database altered.


SQL> select name,open_mode,database_role,db_unique_name,name,flashback_on,log_mode,force_logging,checkpoint_change#,controlfile_change# from v$database;


NAME ,OPEN_MODE       ,DATABASE_ROLE   ,DB_UNIQUE_NAME       ,NAME ,FLASHBACK_ON   ,LOG_MODE ,FORCE_LOGGING ,CHECKPOINT_CHANGE#,CONTROLFILE_CHANGE#

---------,--------------------,----------------,------------------------------,---------,------------------,------------,---------------------------------------,------------------,-------------------

GGTGT04T ,READ WRITE       ,PRIMARY       ,GGTGT04T       ,GGTGT04T ,RESTORE POINT ONLY,ARCHIVELOG ,YES ,     1118168, 1118425


SQL>



7. Load the data back from csv file to another schema and tablespace


create user ENCVAULT_TEST_PREV identified by ENCVAULT_TEST_PREV default tablespace USERS;

alter user ENCVAULT_TEST_PREV quota unlimited on USERS;


drop table ENCVAULT_TEST_PREV.ENCRYPT_TAB1_EXT;

CREATE TABLE ENCVAULT_TEST_PREV.ENCRYPT_TAB1_EXT ("OWNER" VARCHAR2(128),

"OBJECT_NAME" VARCHAR2(128),

"SUBOBJECT_NAME" VARCHAR2(128),

"OBJECT_ID" NUMBER,

"DATA_OBJECT_ID" NUMBER,

"OBJECT_TYPE" VARCHAR2(23),

"CREATED" DATE,

"LAST_DDL_TIME" DATE,

"TIMESTAMP" VARCHAR2(19),

"STATUS" VARCHAR2(7),

"TEMPORARY" VARCHAR2(1),

"GENERATED" VARCHAR2(1),

"SECONDARY" VARCHAR2(1),

"NAMESPACE" NUMBER,

"EDITION_NAME" VARCHAR2(128),

"SHARING" VARCHAR2(18),

"EDITIONABLE" VARCHAR2(1),

"ORACLE_MAINTAINED" VARCHAR2(1),

"APPLICATION" VARCHAR2(1),

"DEFAULT_COLLATION" VARCHAR2(100),

"DUPLICATED" VARCHAR2(1),

"SHARDED" VARCHAR2(1),

"CREATED_APPID" NUMBER,

"CREATED_VSNID" NUMBER,

"MODIFIED_APPID" NUMBER,

"MODIFIED_VSNID" NUMBER

)

ORGANIZATION EXTERNAL (

  TYPE ORACLE_LOADER

  DEFAULT DIRECTORY DATA_PUMP_DIR

  ACCESS PARAMETERS (

    FIELDS TERMINATED BY "," LDRTRIM

    MISSING FIELD VALUES ARE NULL

    REJECT ROWS WITH ALL NULL FIELDS

("OWNER" CHAR(128),

"OBJECT_NAME" CHAR(128),

"SUBOBJECT_NAME" CHAR(128),

"OBJECT_ID" CHAR(100),

"DATA_OBJECT_ID" CHAR(100),

"OBJECT_TYPE" CHAR(23),

"CREATED" DATE "DD/MM/YYYY HH24:MI:SS",

"LAST_DDL_TIME" DATE "DD/MM/YYYY HH24:MI:SS",

"TIMESTAMP" CHAR(19),

"STATUS" CHAR(7),

"TEMPORARY" CHAR(1),

"GENERATED" CHAR(1),

"SECONDARY" CHAR(1),

"NAMESPACE" CHAR(100),

"EDITION_NAME" CHAR(128),

"SHARING" CHAR(18),

"EDITIONABLE" CHAR(1),

"ORACLE_MAINTAINED" CHAR(1),

"APPLICATION" CHAR(1),

"DEFAULT_COLLATION" CHAR(100),

"DUPLICATED" CHAR(1),

"SHARDED" CHAR(1),

"CREATED_APPID" CHAR(100),

"CREATED_VSNID" CHAR(100),

"MODIFIED_APPID" CHAR(100),

"MODIFIED_VSNID" CHAR(100)

)

)

LOCATION (

'ENCRYPT_TAB1.csv'

)

);



drop table ENCVAULT_TEST_PREV.GGTEST1_EXT;

CREATE TABLE ENCVAULT_TEST_PREV.test_EXT (

"EID" NUMBER,

"PINCODE" NUMBER,

"BRANCHCODE" VARCHAR2(4000),

"ENAME" VARCHAR2(4000)

)

ORGANIZATION EXTERNAL (

  TYPE ORACLE_LOADER

  DEFAULT DIRECTORY DATA_PUMP_DIR 

  ACCESS PARAMETERS (

    FIELDS TERMINATED BY "," LDRTRIM

    MISSING FIELD VALUES ARE NULL

    REJECT ROWS WITH ALL NULL FIELDS

    )

  LOCATION ('30Sep2023_actual_GGTEST1.csv'));


create table ENCVAULT_TEST_PREV.ENCRYPT_TAB1

as

select * from ENCVAULT_TEST.ENCRYPT_TAB1 where 1=2;


insert into ENCVAULT_TEST_PREV.ENCRYPT_TAB1

select * from ENCVAULT_TEST_PREV.ENCRYPT_TAB1_EXT;


commit;


create table ENCVAULT_TEST_PREV.GGTEST1

as

select * from ENCVAULT_TEST.GGTEST1 where 1=2;


insert into ENCVAULT_TEST_PREV.GGTEST1

select * from ENCVAULT_TEST.GGTEST1;t


commit;


Actual output:


SQL> create user ENCVAULT_TEST_PREV identified by ENCVAULT_TEST_PREV default tablespace USERS;


User created.


SQL> alter user ENCVAULT_TEST_PREV quota unlimited on USERS;


User altered.


SQL> drop table ENCVAULT_TEST_PREV.ENCRYPT_TAB1_EXT;

drop table ENCVAULT_TEST_PREV.ENCRYPT_TAB1_EXT

                              *

ERROR at line 1:

ORA-00942: table or view does not exist



SQL> CREATE TABLE ENCVAULT_TEST_PREV.ENCRYPT_TAB1_EXT ("OWNER" VARCHAR2(128),

"OBJECT_NAME" VARCHAR2(128),

"SUBOBJECT_NAME" VARCHAR2(128),

"OBJECT_ID" NUMBER,

"DATA_OBJECT_ID" NUMBER,

"OBJECT_TYPE" VARCHAR2(23),

"CREATED" DATE,

"LAST_DDL_TIME" DATE,

"TIMESTAMP" VARCHAR2(19),

"STATUS" VARCHAR2(7),

"TEMPORARY" VARCHAR2(1),

"GENERATED" VARCHAR2(1),

"SECONDARY" VARCHAR2(1),

"NAMESPACE" NUMBER,

"EDITION_NAME" VARCHAR2(128),

"SHARING" VARCHAR2(18),

"EDITIONABLE" VARCHAR2(1),

  2    3    4    5    6    7    8    9   10   11   12   13   14   15   16   17   18  "ORACLE_MAINTAINED" VARCHAR2(1),

"APPLICATION" VARCHAR2(1),

"DEFAULT_COLLATION" VARCHAR2(100),

"DUPLICATED" VARCHAR2(1),

"SHARDED" VARCHAR2(1),

"CREATED_APPID" NUMBER,

"CREATED_VSNID" NUMBER,

"MODIFIED_APPID" NUMBER,

"MODIFIED_VSNID" NUMBER

)

ORGANIZATION EXTERNAL (

  TYPE ORACLE_LOADER

  DEFAULT DIRECTORY DATA_PUMP_DIR

  ACCESS PARAMETERS (

 19   20   21   22   23   24   25   26   27   28   29   30   31   32      FIELDS TERMINATED BY "," LDRTRIM

    MISSING FIELD VALUES ARE NULL

    REJECT ROWS WITH ALL NULL FIELDS

("OWNER" CHAR(128),

"OBJECT_NAME" CHAR(128),

"SUBOBJECT_NAME" CHAR(128),

"OBJECT_ID" CHAR(100),

"DATA_OBJECT_ID" CHAR(100),

"OBJECT_TYPE" CHAR(23),

"CREATED" DATE "DD/MM/YYYY HH24:MI:SS",

"LAST_DDL_TIME" DATE "DD/MM/YYYY HH24:MI:SS",

"TIMESTAMP" CHAR(19),

"STATUS" CHAR(7),

"TEMPORARY" CHAR(1),

"GENERATED" CHAR(1),

"SECONDARY" CHAR(1),

"NAMESPACE" CHAR(100),

"EDITION_NAME" CHAR(128),

"SHARING" CHAR(18),

"EDITIONABLE" CHAR(1),

"ORACLE_MAINTAINED" CHAR(1),

"APPLICATION" CHAR(1),

"DEFAULT_COLLATION" CHAR(100),

"DUPLICATED" CHAR(1),

"SHARDED" CHAR(1),

"CREATED_APPID" CHAR(100),

"CREATED_VSNID" CHAR(100),

"MODIFIED_APPID" CHAR(100),

"MODIFIED_VSNID" CHAR(100)

)

)

LOCATION (

'ENCRYPT_TAB1.csv'

)

); 33   34   35   36   37   38   39   40   41   42   43   44   45   46   47   48   49   50   51   52   53   54   55   56   57   58   59   60   61   62   63   64   65   66


Table created.


SQL> create table ENCVAULT_TEST_PREV.ENCRYPT_TAB1

as

select * from ENCVAULT_TEST.ENCRYPT_TAB1 where 1=2;  2    3


Table created.


SQL> insert into ENCVAULT_TEST_PREV.ENCRYPT_TAB1

select * from ENCVAULT_TEST_PREV.ENCRYPT_TAB1_EXT;  2


10 rows created.


SQL> select count(1) from ENCVAULT_TEST_PREV.ENCRYPT_TAB1;


  COUNT(1)

----------

        10


SQL>


SQL> select * from ENCVAULT_TEST_PREV.ENCRYPT_TAB1;


OWNER

--------------------------------------------------------------------------------------------------------------------------------

..

 11,            11,INDEX                  ,24-AUG-23,24-AUG-23

2023-08-24:19:32:14,VALID  ,N,N,N,         4,                                                                                 ,NONE               , ,Y,N

                                                                                                    ,N,N,             ,      ,               ,



10 rows selected.


SQL>



Just to make sure if the records are properly loaded with proper column width and info. I compared the output of ENCVAULT_TEST_PREV.ENCRYPT_TAB1 & ENCVAULT_TEST.ENCRYPT_TAB1

and learnt that they are very clean. I will upload the notepad++ diff output below for reference.


A quick view on the restored and actual table comparison in notepad++ (luckily I didnt make any change to the table in the recent past, they dont show difference because of it).



YouTube video:


No comments:

Post a Comment

Flashback data archive steps

 Objective: Ways to track DML changes in a table Detailed objective: We should be able to track the changes in the table at any point in tim...