/*************************************************************************************
 * @author                        :  Chandar
 * @version                       :  1.0
 *
 * Name of the Application        :  AddTable.sql
 * Creation/Modification History  :
 *
 *    Chandar        02-Feb-2003       Created
 *
 * Overview of Script:
 * This SQL scripts adds another table to existing streams environment for
 * bi-directional replication between two databases without quiescing the exisiting
 * processes. Replication is set up for the table named tabtwo in strmuser schema.
 * The initial streams setup is done by StreamsSetup.sql script.

 * Note:
 * 1. Ensure that you have created a streams administrator before executing this script.
 *    The script StreamsAdminConfig.sql can be used to create a streams administrator
 *    and configure it.
 *
 * 2. Setup the streams for replication for the first time using SetupStreams.sql .
***************************************************************************************/

SET VERIFY OFF
SET ECHO OFF
SPOOL add_table.log

--define variables to store global names of two databases

variable site1 varchar2(128);
variable site2 varchar2(128);
variable scn number;

--------------------------------------------------------------------
-- get TNSNAME and streams admin user details for both the databases
--------------------------------------------------------------------
PROMPT
-- TNSNAME for database 1
ACCEPT db1 PROMPT 'Enter TNS Name of first database :'

PROMPT
-- Streams administrator username for database 1
ACCEPT strm_adm_db1 PROMPT 'Enter username for streams admin of first database :'

PROMPT
-- Streams administrator password for database 1
ACCEPT strm_adm_pwd_db1 PROMPT 'Enter password for streams admin on first database :'


PROMPT
-- TNSNAME for database 2
ACCEPT db2 PROMPT 'Enter TNS Name of second database :'

PROMPT
-- Streams administrator username for database 2
ACCEPT strm_adm_db2 PROMPT 'Enter username for streams admin of second database :'

PROMPT
-- Streams administrator password for database 2
ACCEPT strm_adm_pwd_db2 PROMPT 'Enter password for streams admin on second database :'


------------------------------------------------------
--create table tabtwo in strmuser schema in database 1
------------------------------------------------------

PROMPT Connecting as strmuser to database 1

CONN strmuser/strmuser@&db1

-- create a sample table named tabtwo for which the replication will be set up

PROMPT
PROMPT Creating table  tabtwo

CREATE TABLE tabtwo (id NUMBER(5) PRIMARY KEY, name VARCHAR2(50));

-- grant all permissions on tabtwo to streams administrator

PROMPT  Granting all permission on tabtwo to streams administrator

GRANT ALL ON strmuser.tabtwo TO &strm_adm_db1;

PROMPT Inserting sample rows in tabtwo table

INSERT INTO tabtwo VALUES(1,'Mark');
INSERT INTO tabtwo VALUES(2,'Viru');

COMMIT;

PROMPT Adding supplemetal logging for table tabtwo

ALTER TABLE tabtwo ADD SUPPLEMENTAL LOG GROUP tabtwo_log_group ( id,name) ALWAYS;



-- connect as streams administrator to database 2

PROMPT  Connecting as streams administrator to database 2

CONN &strm_adm_db2/&strm_adm_pwd_db2@&db2

-- Store global name in site2 variable

PROMPT
PROMPT Getting global name of database 2

EXECUTE SELECT global_name INTO :site2 FROM global_name;


PROMPT Executing wait.sql to load wait_until procedure

@@wait.sql


-- connect as streams administrator to database 1

PROMPT Connecting as streams administrator to database 1

CONN &strm_adm_db1/&strm_adm_pwd_db1@&db1

-- Store global name in site1 variable

PROMPT
PROMPT Get the global name of database 1

EXECUTE SELECT global_name INTO :site1 FROM global_name;

PROMPT Executing wait.sql to load wait_until procedure

@@wait.sql


--set up a new temporary queue

PROMPT Creating a temporary queue at database 1

BEGIN
  DBMS_STREAMS_ADM.SET_UP_QUEUE(
    queue_table  => 'temp_queue_table',
    queue_name   => 'temp_queue',
    queue_user   => 'strmuser');
END;
/


-- create a new capture process and add table rules for table tabtwo to capture the
-- changes made to tabtwo in database 1

PROMPT  Creating a temporary capture process at database 1 and adding table rules for tabtwo

BEGIN
  DBMS_STREAMS_ADM.ADD_TABLE_RULES(
    table_name     => 'strmuser.tabtwo',
    streams_type   => 'capture',
    streams_name   => 'tempcapture',
    queue_name     => '&strm_adm_db1..temp_queue',
    include_dml    =>  true,
    include_ddl    =>  true);
END;
/

-- Add table propagation rules for table tabtwo to a new propagation process
-- to propagate captured changes from database 1 to database2

PROMPT Adding propagation rules for tabtwo to temporary propagation process at database 1

BEGIN
  DBMS_STREAMS_ADM.ADD_TABLE_PROPAGATION_RULES(
    table_name              => 'strmuser.tabtwo',
    streams_name            => 'tempprop',
    source_queue_name       => '&strm_adm_db1..temp_queue',
    destination_queue_name  => '&strm_adm_db2..temp_queue@'||:site2,
    include_dml             =>  true,
    include_ddl             =>  true,
    source_database         => :site1);
END;
/


-- connect to database 2 as streams administrator

PROMPT Connecting as streams administrator to database 2

CONN &strm_adm_db2/&strm_adm_pwd_db2@&db2


-- create a new temporary queue

PROMPT Creating a temporary queue at database 2

BEGIN
  DBMS_STREAMS_ADM.SET_UP_QUEUE(
    queue_table  => 'temp_queue_table',
    queue_name   => 'temp_queue',
    queue_user   => 'strmuser');
END;
/

-- create a new apply process and add table rules for table tabtwo to apply
-- any changes propagated from database 1

PROMPT Creating a temporary apply process at database 2 and adding table rules
       for tabtwo

BEGIN
  DBMS_STREAMS_ADM.ADD_TABLE_RULES(
    table_name      => 'strmuser.tabtwo',
    streams_type    => 'apply',
    streams_name    => 'tempapply',
    queue_name      => '&strm_adm_db2..temp_queue',
    include_dml     =>  true,
    include_ddl     =>  true,
    source_database => :site1);
END;
/


PROMPT Table tabtwo has to be exported from database 1 and imported to database 2
PROMP so that the two databases are in sync and tabtwo is instantiated at database 2
PROMPT

HOST exp USERID=strmuser/strmuser@&db1 FILE=strmuser.dmp TABLES=tabtwo
         OBJECT_CONSISTENT=y ROWS=y

HOST imp USERID=strmuser/strmuser@&db2 FILE=strmuser.dmp IGNORE=y COMMIT=y
         LOG=import.log STREAMS_INSTANTIATION=y


GRANT ALL ON strmuser.tabtwo TO &strm_adm_db1;


PROMPT Connecting as strmuser to database 2

CONN strmuser/strmuser@&db2

-- grant all permissions on tabtwo to streams administration

PROMPT  Granting all permission on tabtwo to streams administrator

GRANT ALL ON strmuser.tabtwo TO &strm_adm_db2;



-----------------------------------------------------
-- set up bi-directional replication for table tabtwo
------------------------------------------------------

-- connect to database 2 as streams administrator

PROMPT Connecting as streams administrator to database 2

CONN &strm_adm_db2/&strm_adm_pwd_db2@&db2


PROMPT
-- add table rules for table tabtwo to original capture process to capture the
-- changes made to tabtwo in database 2

PROMPT Adding table rules for tabtwo to original capture process at database 2

BEGIN
  DBMS_STREAMS_ADM.ADD_TABLE_RULES(
    table_name     => 'strmuser.tabtwo',
    streams_type   => 'capture',
    streams_name   => 'capture_db2',
    queue_name     => '&strm_adm_db2..strmuser_queue',
    include_dml    =>  true,
    include_ddl    =>  true);
END;
/

-- Add table propagation rules for table tabtwo to original propagation
-- process to propagate capture changes from database 2 to database 1

PROMPT Adding table propagation rules for tabtwo to original propagation
       process at database 2

BEGIN
  DBMS_STREAMS_ADM.ADD_TABLE_PROPAGATION_RULES(
    table_name              => 'strmuser.tabtwo',
    streams_name            => 'db2_to_db1_prop',
    source_queue_name       => '&strm_adm_db2..strmuser_queue',
    destination_queue_name  => '&strm_adm_db1..strmuser_queue@'||:site1,
    include_dml             =>  true,
    include_ddl             =>  true,
    source_database         => :site2);
END;
/

-- connect to database 1 as streams administrator

PROMPT  Connecting as streams administrator to database 1

CONN &strm_adm_db1/&strm_adm_pwd_db1@&db1

PROMPT Adding table rule for tabtwo at database 1 to original apply process

BEGIN
  DBMS_STREAMS_ADM.ADD_TABLE_RULES(
    table_name      => 'strmuser.tabtwo',
    streams_type    => 'apply',
    streams_name    => 'apply_db1',
    queue_name      => '&strm_adm_db1..strmuser_queue',
    include_dml     =>  true,
    include_ddl     =>  true,
    source_database => :site2);
END;
/

-- connect to database 2 as streams administrator

PROMPT  Connecting as streams administrator to database 2

CONN &strm_adm_db2/&strm_adm_pwd_db2@&db2

PROMPT
-- get the current SCN of database 2

PROMPT Getting current SCN of database 2

EXECUTE :scn := DBMS_FLASHBACK.GET_SYSTEM_CHANGE_NUMBER();


-- connect to database 1 as streams administrator

PROMPT Connecting as streams administrator to database 1

CONN &strm_adm_db1/&strm_adm_pwd_db1@&db1

-- Set table instantiation SCN for table tabtwo at database 1 to current
-- SCN of database 2

PROMPT
PROMPT Setting instatiation SCN for tabtwo at database 1

BEGIN
  DBMS_APPLY_ADM.SET_TABLE_INSTANTIATION_SCN(source_object_name  => 'strmuser.tabtwo',
                                             source_database_name => :site2,
                                             instantiation_scn =>:scn);
END;
/


-----------------------------
--End of bi-directional setup
-----------------------------

-- connect to database 2 as streams administrator

PROMPT  Connecting as streams administrator to database 2

CONN &strm_adm_db2/&strm_adm_pwd_db2@&db2

PROMPT
-- start the new temporary apply process at database 2

PROMPT Starting the apply process

BEGIN
  DBMS_APPLY_ADM.START_APPLY(
    apply_name  => 'tempapply');
END;
/

-- connect to database 1 as streams administrator

PROMPT Connecting as streams administrator to database 1

CONN &strm_adm_db1/&strm_adm_pwd_db1@&db1

-- start the new capture process at database 1

PROMPT
PROMPT Starting the temporary capture process at database 1

BEGIN
  DBMS_CAPTURE_ADM.START_CAPTURE(
    capture_name  => 'tempcapture');
END;
/

-- make dml changes to tabtwo to check if new streams processes are working

PROMPT Inserting row in tabtwo at database 1 to see if changes are captured and propagated

INSERT INTO strmuser.tabtwo VALUES (3,'Stuart');

COMMIT;

-- now add table rules for table tabtwo to original capture process to capture the
-- changes made to tabtwo in database 1

PROMPT Adding table capture rules for tabtwo to original cature process at database 1

BEGIN
  DBMS_STREAMS_ADM.ADD_TABLE_RULES(
    table_name     => 'strmuser.tabtwo',
    streams_type   => 'capture',
    streams_name   => 'capture_db1',
    queue_name     => '&strm_adm_db1..strmuser_queue',
    include_dml    =>  true,
    include_ddl    =>  true);
END;
/


-- Add table propagation rules for table tabtwo to original propagation process
-- to propagate captured changes from database 1 to database 2

PROMPT Adding table propagation rules for tabtwo to original propagation process
       at database 1

BEGIN
  DBMS_STREAMS_ADM.ADD_TABLE_PROPAGATION_RULES(
    table_name              => 'strmuser.tabtwo',
    streams_name            => 'db1_to_db2_prop',
    source_queue_name       => '&strm_adm_db1..strmuser_queue',
    destination_queue_name  => '&strm_adm_db2..strmuser_queue@'||:site2,
    include_dml             =>  true,
    include_ddl             =>  true,
    source_database         => :site1);
END;
/

-----------------------------------------------------------------------
-- Get a shared lock on tabtwo at database 1 and obtain the current scn.
-- The shared lock is needed so that we can be sure there are no
-- transactions in progress during the time we get the current scn.
-- If not, we may end up losing some LCRs.
-----------------------------------------------------------------------

PROMPT Getting a shared lock on table tabtwo

LOCK TABLE strmuser.tabtwo IN SHARE MODE;


PROMPT Get current SCN of database 1 and set it as max SCN for temporary capture
       process at database 1 and original apply process at database 2

-- This has to be done in different session because SET_PARAMETER procedure does
-- an implicit commit which will release the lock on tabtwo table in this session.

PROMPT
PROMPT This is to be done in a different session. The current session will
PROMPT hang and wait for a message from new session to contiue further

PROMPT
PROMPT Connect to SQL PLUS from a new command window as any user to database 1 and
       execute script SetParams.sql located at /scripts directory.
       When this script completes, it sends message to this session to continue.

PROMPT
PROMPT Waiting till new session sends a message to continue. Do not close this window.

EXECUTE wait_until('s1','s2','1.2');

PROMPT Recevied message to continue

-- release lock on tabtwo at database 1 using commit


PROMPT  Releasing the shared lock of table tabtwo at database 1

COMMIT;


-- connect to database 2 as streams administrator

PROMPT  Connecting as streams administrator to database 2

CONN &strm_adm_db2/&strm_adm_pwd_db2@&db2

--Perform some DML so that SCN increases

PROMPT Performing DML on database 2 so that SCN increases

INSERT INTO strmuser.tabone VALUES(53,'Joe');
COMMIT;

INSERT INTO strmuser.tabone VALUES(54,'John');
COMMIT;

INSERT INTO strmuser.tabone VALUES(55,'Jacob');
COMMIT;

INSERT INTO strmuser.tabone VALUES(56,'Jim');
COMMIT;

INSERT INTO strmuser.tabone VALUES(57,'Saurav');
COMMIT;

UPDATE  strmuser.tabone SET name='Carl' WHERE name='John';
COMMIT;

UPDATE  strmuser.tabone SET name='Greg' WHERE name='Joe';
COMMIT;

UPDATE  strmuser.tabone SET name='Sam' WHERE name='Jacob';
COMMIT;

UPDATE  strmuser.tabone SET name='Kashish' WHERE name='Jim';
COMMIT;

UPDATE  strmuser.tabone SET name='Molly' WHERE name='Saurav';

COMMIT;

PROMPT Waiting for original apply process to get disabled because of reaching maximum SCN
EXECUTE DBMS_LOCK.SLEEP(60);

-- When original apply process is disabled because maximum SCN has reached,
-- add table rules for table tabtwo to apply any changes propagated from database 1

PROMPT When original apply process at database 2 is disabled
PROMPT Adding table rules for tabtwo to original apply process at database 2

BEGIN
  DBMS_STREAMS_ADM.ADD_TABLE_RULES(
    table_name      => 'strmuser.tabtwo',
    streams_type    => 'apply',
    streams_name    => 'apply_db2',
    queue_name      => '&strm_adm_db2..strmuser_queue',
    include_dml     =>  true,
    include_ddl     =>  true,
    source_database => :site1);
END;
/



-- connect to database 1 as streams administrator

PROMPT Connecting to database 1 as streams administrator

CONN &strm_adm_db1/&strm_adm_pwd_db1@&db1

PROMPT
-- stop the new capture process

PROMPT Stopping the temporary capture process

BEGIN
  DBMS_CAPTURE_ADM.STOP_CAPTURE(
    capture_name =>' tempcapture');
END;
/

-- drop the new capture process

PROMPT Dropping the temporary capture process

BEGIN
  DBMS_CAPTURE_ADM.DROP_CAPTURE(
    capture_name =>' tempcapture');
END;
/

-- drop the new propagation process

PROMPT Dropping the temporary propagation process

BEGIN
  DBMS_PROPAGATION_ADM.DROP_PROPAGATION(
    propagation_name => 'tempprop');
END;
/

-- stop the new temporary queue

PROMPT Stopping the temporary queue at database 1

BEGIN
  DBMS_AQADM.STOP_QUEUE(
    queue_name  => 'temp_queue');
END;
/

-- drop the new temporary queue

PROMPT Dropping the temporary queue at database 1

BEGIN
  DBMS_AQADM.DROP_QUEUE(
    queue_name  => 'temp_queue');
END;
/

-- drop the queue table of new temporary queue

PROMPT Dropping the queue table for temporary queue at database 1

BEGIN
  DBMS_AQADM.DROP_QUEUE_TABLE('temp_queue_table');
END;
/


-- connect to database 2 as streams administrator

PROMPT Connecting as streams administrator to database 2

CONN &strm_adm_db2/&strm_adm_pwd_db2@&db2

-- stop the new apply process

PROMPT
PROMPT Stopping the temporary apply process

BEGIN
  DBMS_APPLY_ADM.STOP_APPLY(
    apply_name  => 'tempapply');
END;
/

-- drop the new apply process

PROMPT Dropping the temporary apply process

BEGIN
  DBMS_APPLY_ADM.DROP_APPLY(
    apply_name  => 'tempapply');
END;
/


-- stop the temporary queue at database 2

PROMPT Stopping the temporary queue at database 2

BEGIN
  DBMS_AQADM.STOP_QUEUE(
    queue_name  => 'temp_queue');
END;
/

-- drop the temporary queue at database 2

PROMPT Dropping the temporary queue at database 2

BEGIN
  DBMS_AQADM.DROP_QUEUE(
    queue_name  => 'temp_queue');
END;
/

-- drop the queue table of new temporary queue

PROMPT Dropping the temporary queue table at database 2

BEGIN
 DBMS_AQADM.DROP_QUEUE_TABLE('temp_queue_table');
END;
/



PROMPT
-- set the maximum_scn parameter for original apply process to infinite

PROMPT Setting the maximum SCN for original apply process at database 2 to infinite

BEGIN
 DBMS_APPLY_ADM.SET_PARAMETER('apply_db2','maximum_scn','infinite');
END;
/

-- start the original apply process

PROMPT Starting the original apply process at database 2
BEGIN
  DBMS_APPLY_ADM.START_APPLY(
    apply_name  => 'apply_db2');
END;
/

PROMPT Performing DML on tabtwo at database 2 to check if setup is working

INSERT INTO strmuser.tabtwo VALUES(61,'shrini');

COMMIT;

PROMPT Wait for some time so that changes are applied to database 1


EXECUTE DBMS_LOCK.SLEEP(30);

-- connect to database 1 as streams administrator

PROMPT Connecting to database 1 as streams administrator

CONN &strm_adm_db1/&strm_adm_pwd_db1@&db1

PROMPT

PROMPT Checking if changes on tabtwo from database 2 are applied at database 1

SELECT * FROM strmuser.tabtwo;

PROMPT Performing DML on tabtwo at database 1

INSERT INTO strmuser.tabtwo VALUES (62,'rajat');

PROMPT Wait for some time so that changes are applied to database 2.

EXECUTE DBMS_LOCK.SLEEP(30);

COMMIT;

-- connect to database 2 as streams administrator

PROMPT Connecting to database 2 as streams administrator

CONN &strm_adm_db2/&strm_adm_pwd_db2@&db2

PROMPT

PROMPT Checking if changes on tabtwo from database 1 are applied at database 2

SELECT * FROM strmuser.tabtwo;



PROMPT End of Script

SPOOL OFF
E-mail this page
Printer View Printer View
Oracle Is The Information Company About Oracle | Oracle RSS Feeds | Careers | Contact Us | Site Maps | Legal Notices | Terms of Use | Privacy