-- Transportable Tablespace Demo
-- Copyright (c) 2005, Caleb.com

-- Setup for the demo
start listener
start database FRED
drop user caleb cascade;
drop tablespaces trans1/2/3 and delete datafiles
create user caleb;
import caleb.dmp (see notes at end of file)

-- Examine tablespaces and objects
set linesize 100
SELECT tablespace_name, status
FROM dba_tablespaces
save ts
SELECT * FROM tab;
save tab

-- Examine constraints and indexes
SELECT table_name, constraint_name, constraint_type AS t, status
FROM user_constraints
ORDER BY table_name, constraint_type;
save cons

SELECT table_name, index_name, tablespace_name
FROM user_indexes
ORDER BY table_name;
save inds

-- Examine triggers
SELECT table_name, trigger_name
FROM user_triggers
ORDER BY table_name;
save trgs

-- Examine grants
SELECT table_name, privilege, grantee
FROM user_tab_privs_made
ORDER BY table_name;
save privs


-- Create the tablespaces that will be transported
CREATE TABLESPACE trans1
DATAFILE '/u01/app/oracle/oratrans/trans1.dbf' size 1M
AUTOEXTEND ON MAXSIZE 50M;
save ts1

CREATE TABLESPACE trans2
DATAFILE '/u01/app/oracle/oratrans/trans2.dbf' size 1M
AUTOEXTEND ON MAXSIZE 50M;
save ts2

CREATE TABLESPACE trans3
DATAFILE '/u01/app/oracle/oratrans/trans3.dbf' size 1M
AUTOEXTEND ON MAXSIZE 50M;
save ts3


-- Move some existing tables into the TTS set
ALTER TABLE employees MOVE TABLESPACE trans1;
save m1
ALTER TABLE departments MOVE TABLESPACE trans2;
save m2

-- Copy another existing table into the TTS set
-- (note there are dependancies between these tables)
CREATE TABLE locations2 TABLESPACE trans2 AS
SELECT * FROM locations;
save c1

-- Rebuild some of the indexes into the TTS set
ALTER INDEX emp_emp_id_pk REBUILD TABLESPACE trans3;
save i1
ALTER INDEX emp_name_ix REBUILD TABLESPACE trans3;
save i2

-- Create a new aggregrate table in the TTS set
CREATE TABLE empsales TABLESPACE trans1 AS
SELECT e.last_name, sum(o.order_total) AS total_orders
FROM employees e, oe.orders o
WHERE e.employee_id(+) = o.sales_rep_id
GROUP BY e.last_name;
save agg

-- Add a new record to prove it's not a trick
INSERT INTO empsales VALUES ('&name', 1000000.5);
save es1
COMMIT;

-- Review what we've created
COLUMN segment_name FORMAT a24
SELECT segment_name, segment_type, tablespace_name
FROM user_segments;
save segs

-- Verify no outside dependancies
EXECUTE sys.DBMS_TTS.TRANSPORT_SET_CHECK('trans1,trans2,trans3', TRUE);
save tts_check
SELECT * FROM sys.TRANSPORT_SET_VIOLATIONS;
save tsv

-- Fix the dependancy by disabling constraint and explain
ALTER TABLE departments DISABLE CONSTRAINT dept_loc_fk;
save a1
ALTER INDEX dept_id_pk REBUILD TABLESPACE trans3;
save a2
ALTER TABLE employees DISABLE CONSTRAINT emp_email_uk;
save a3

-- Make tablespaces read only in preparation for transport
ALTER TABLESPACE trans1 READ ONLY;
ALTER TABLESPACE trans2 READ ONLY;
ALTER TABLESPACE trans3 READ ONLY;
save ro

-- Again verify no outside dependancies
@tts_check
@tsv

-- Ensure an Oracle Directory exists for the metadata export
CREATE OR REPLACE DIRECTORY trans_dir AS '/u01/app/oracle/oratrans';
save d1
GRANT READ, WRITE ON DIRECTORY trans_dir TO public;
save d2

-- Perform the metadata export
expdp caleb/small@FRED \
DUMPFILE=trans.dmp \
DIRECTORY=trans_dir \
TRANSPORT_TABLESPACES = trans1,trans2,trans3
-- or old way
exp TRANSPORT_TABLESPACE=y TABLESPACES=trans1 FILE=$ORACLE_BASE/oratrans/trans.dmp
sys@FRED as sysdba

-- Copy the tablespace data files and metadata export file to the target system
cd $ORACLE_BASE/oratrans
cp * /shrdat/oratrans

-- OR user RMAN to perform copy (required to convert)
rman target fred
CONVERT TABLESPACE trans1, trans2, trans3
TO PLATFORM 'Microsoft Windows IA (32-bit)'
FORMAT='$ORACLE_BASE/oratrans/%N_win.dbf';


-- At this point we are finished in the source DB.  
-- The tablespaces are still available to users in read-only mode.
-- We can make them read-write again after the copy or conversion is done.
ALTER TABLESPACE trans1 READ WRITE;
ALTER TABLESPACE trans2 READ WRITE;
ALTER TABLESPACE trans3 READ WRITE;
save rw

-- If an RMAN conversion was required due to endianness we could
-- do it either on the source system before transport, or on the
-- target system after transport.
COLUMN platform_name FORMAT a40
SELECT * FROM V$TRANSPORTABLE_PLATFORM
ORDER BY platform_id;
save ts_platform

-- Fire up the target system!

-- Setup required in both DBs
DROP USER bentley CASCADE;
DROP TABLESPACE trans1;
DROP TABLESPACE trans2;
DROP TABLESPACE trans3;
CREATE USER bentley IDENTIFIED BY stillmore
DEFAULT TABLESPACE users TEMPORARY TABLESPACE temp;
GRANT connect, resource, dba TO bentley;
cd d:\oradata\oratrans
del trans*.dbf
del trans.dmp


-- review tablespaces and objects
CONNECT bentley/stillmore@bing
@ts
@segs


-- Note: when creating all of the databases, the character sets must match:
-- NLS_CHARACTERSET = WE8ISO8859P1 (not the windows default!)
-- NLS_NCHAR_CHARACTERSET = AL16UTF16
SELECT * FROM v$nls_parameters
WHERE parameter IN ('NLS_CHARACTERSET','NLS_NCHAR_CHARACTERSET');
save charset


-- Ensure an Oracle Directory exists for the metadata import
CREATE OR REPLACE DIRECTORY trans_dir AS 'd:/oradata/oratrans';
save d1
GRANT READ, WRITE ON DIRECTORY trans_dir TO public;
save d2

-- Copy the files to the target directory

-- Import the metadata into the target system
impdp bentley/stillmore@bing parfile=trans.par
	DUMPFILE=trans.dmp 
	DIRECTORY=trans_dir 
	REMAP_SCHEMA=caleb:bentley
	TRANSPORT_DATAFILES='d:\oradata\oratrans\trans1.dbf',
                            'd:\oradata\oratrans\trans2.dbf',
                            'd:\oradata\oratrans\trans3.dbf' 
-- or the old way
imp transport_tablespace=y DATAFILEs='f:\oratrans\trans1.dbf' tablespaces=trans1 file='f:\oratrans\trans.dmp'

-- Query the data
SELECT * FROM tab;
@emps
@empsales

-- Show location of data (tablespace and DATAFILE)
@tabs

-- Show constraints and indexes are intact
@inds
@cons

-- Show triggers are intact
@trgs

-- Show grants
@privs

-- Demonstrate that we can 'plug in' the same tablespaces concurrently
-- into another database if all are read-only access

-- Import the metadata into a second target
CONNECT bentley/stillmore@bong
@d1
@d2
impdp ...
@tabs


SETUP notes:
------------
export hr schema and import into caleb
drop all but employees, departments and locations tables
compute statistics
GRANT SELECT on EMPLOYEES to moe, larry, joe;
CREATE VIEW view depsum AS
    SELECT d.department_name, sum(e.salary) cost
    FROM departments d, employees e
    WHERE d.department_id = e.department_id
    GROUP BY d.department_name;
CREATE OR REPLACE TRIGGER emp_sal
BEFORE insert OR update ON employees
FOR EACH ROW
BEGIN
  IF (:new.salary < 0) THEN
      raise_application_error(-20001,'Salary must must not be negative');
  END IF;
END;
/
export as caleb.dmp for re-use
