Christopher Poole Oracle Database Consultancy
DBA Tips
Home My CV Applications Tips About
     
 
01 May 2008 - Cloning a user      
       

/*
-- This tip was inspired by a posting on the OTN Database General forum,
-- where I am known to hang out and attempt to answer questions.
--
-- Creating new users is a common DBA requirement and sometimes a user needs to be created
-- as a clone of another user. The easiest way to do this is using the export and import
-- utilities by doing a fromuser export and a touser import. Naturally the downside of this
-- technique is the writing of the export file to disk which takes up space and wastes time.
-- The thread starter wanted to know if there was another way to do this.
--
-- However in 10g the new Datapump utility that replaces the old fashioned exp/imp has the
-- ability to do imports over a database link, which means that no file needs to be written to.
--
-- The trick to the technique is knowing that a database link can connect to the same database
-- the user is connected to; this technique is known as a loopback database link.
-- An import Datapump job can then be opened over the link and then it's just a matter of
-- specifying the remapping of the schema name. The import flows through the link requiring no
-- dump file to be written. Since it's optional to even create a log file for the operation,
-- no files need to be written at all. The end result is a much faster technique that requires
-- no external diskspace.
--
-- Testing showed that the user created was an exact replica, right down to the password hash,
-- requiring a change of password as the new user would not be able to login.
--
-- The code below is just a demonstration illustrating a minimal stored procedure
-- implementation that can be executed to clone a user from another user.
-- The code works as intended and has been tested on 10.1.0.5 and 10.2.0.3 but does not
-- include:
-- 1) input sanity checking (Datapump produces generic unhelpful messages
-- if any of the inputs isn't valid or the database link does not work)
-- 2) exception handling (exceptions generated during the import are also generic and
-- unhelpful, details must be obtained using dbms_datapump.get_status)
-- 3) checking for successful completion after the job has finshed
-- 4) atomicity (if the import is not successful the user should really be dropped)
-- Lastly the procedure should be invokers rights not definers as befits a utility.
-- All this is left as an exercise for the reader!
--
-- With thanks to Jim Phillips, the poster of the thread that inspired the code and
-- this tip.
--
*/

create public database link loopback
using
'(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=127.0.0.1)(PORT=1521))(CONNECT_DATA=(SERVER=DEDICATED)(SERVICE_NAME=&your_DB_service_name)))'
;




CREATE OR REPLACE PROCEDURE copy_schema (
source_schema in varchar2,
destination_schema in varchar2,
new_password in varchar2,
network_link in varchar2 default 'loopback'
) as
h number; -- job handle
js user_datapump_jobs.state%type; -- to hold job status
q varchar2(1) := chr(39); -- single quote

BEGIN

/* open a new schema level import job using our loopback DB link */
h := dbms_datapump.open (
'IMPORT',
'SCHEMA',
network_link
);

/* make any data copied consistent with respect to now */
dbms_datapump.set_parameter(h, 'FLASHBACK_SCN', dbms_flashback.get_system_change_number);

/* restrict to the schema we want to copy */
dbms_datapump.metadata_filter (
h,
'SCHEMA_LIST',
q||source_schema||q
);

/* remap the importing schema name to the schema we want to create */
dbms_datapump.metadata_remap(h,'REMAP_SCHEMA',source_schema,destination_schema);

/* start the job */
dbms_datapump.start_job(h);

/* wait for the job to finish */
dbms_datapump.wait_for_job(h, js);

/* change the password as the new user has the same password hash as the old user,
which means the new user can't login! */
execute immediate 'alter user '||destination_schema||' identified by '||new_password;

end;
/

     
       
 

 


Copyright © Christopher Poole
31 May 2007
Disclaimer