Clone a Database User by Query

Script to pull/show a database user’s privileges or clone a user by query.

CREATE OR REPLACE PROCEDURE ASSIGNMENT2(P_USERNAME1 VARCHAR2, P_USERNAME2 VARCHAR2)
IS
CURSOR CUR_PRIV IS SELECT A.*
    FROM (SELECT GRANTEE          USERNAME,
                 GRANTED_ROLE     PRIVILEGE,
                 '--'             OWNER,
                 '--'             TABLENAME,
                 '--'             COLUMN_NAME,
                 ADMIN_OPTION     ADMIN_OPTION,
                 'ROLE'           ACCESS_TYPE
            FROM DBA_ROLE_PRIVS RP JOIN DBA_ROLES R ON RP.GRANTED_ROLE = R.ROLE
           WHERE GRANTEE IN (SELECT USERNAME FROM DBA_USERS WHERE USERNAME = UPPER(P_USERNAME1))
          UNION
          SELECT GRANTEE          USERNAME,
                 PRIVILEGE        PRIVILEGE,
                 '--'             OWNER,
                 '--'             TABLENAME,
                 '--'             COLUMN_NAME,
                 ADMIN_OPTION     ADMIN_OPTION,
                 'SYSTEM'         ACCESS_TYPE
            FROM DBA_SYS_PRIVS
           WHERE GRANTEE IN (SELECT USERNAME FROM DBA_USERS WHERE USERNAME = UPPER(P_USERNAME1))
          UNION
          SELECT GRANTEE        USERNAME,
                 PRIVILEGE      PRIVILEGE,
                 OWNER          OWNER,
                 TABLE_NAME     TABLENAME,
                 '--'           COLUMN_NAME,
                 GRANTABLE      ADMIN_OPTION,
                 'TABLE'        ACCESS_TYPE
            FROM DBA_TAB_PRIVS
           WHERE GRANTEE IN (SELECT USERNAME FROM DBA_USERS WHERE USERNAME = UPPER(P_USERNAME1))
          UNION
          SELECT DP.GRANTEE      USERNAME,
                 PRIVILEGE       PRIVILEGE,
                 OWNER           OWNER,
                 TABLE_NAME      TABLENAME,
                 COLUMN_NAME     COLUMN_NAME,
                 '--'            ADMIN_OPTION,
                 'ROLE'          ACCESS_TYPE
            FROM ROLE_TAB_PRIVS RP, DBA_ROLE_PRIVS DP
           WHERE     RP.ROLE = DP.GRANTED_ROLE
                 AND DP.GRANTEE IN (SELECT USERNAME FROM DBA_USERS WHERE USERNAME = UPPER(P_USERNAME1))
          UNION
          SELECT GRANTEE         USERNAME,
                 PRIVILEGE       PRIVILEGE,
                 OWNER           OWNER,
                 TABLE_NAME      TABLENAME,
                 COLUMN_NAME     COLUMN_NAME,
				 GRANTABLE       ADMIN_OPTION,                 
                 'COLUMN'        ACCESS_TYPE
            FROM DBA_COL_PRIVS
           WHERE GRANTEE IN (SELECT USERNAME FROM DBA_USERS WHERE USERNAME = UPPER(P_USERNAME1))) A;
		   
	BEGIN
		FOR REC IN CUR_PRIV
        LOOP
            BEGIN
				IF (REC.PRIVILEGE LIKE 'CREATE %') OR (REC.PRIVILEGE LIKE 'DROP%') OR (REC.PRIVILEGE LIKE 'ALTER%') THEN
					IF REC.ACCESS_TYPE = 'SYSTEM' THEN
						DBMS_OUTPUT.PUT_LINE('REVOKE ' || REC.PRIVILEGE || ' FROM ' || P_USERNAME2 || ';');
					ELSE
						DBMS_OUTPUT.PUT_LINE('REVOKE ' || REC.PRIVILEGE || ' ON ' || REC.OWNER ||'.'|| REC.TABLENAME || ' FROM ' || P_USERNAME2 || ';');
					END IF;
				ELSE 
					IF REC.COLUMN_NAME <> '--' THEN
						DBMS_OUTPUT.PUT_LINE('GRANT ' || REC.PRIVILEGE || ' (' || REC.COLUMN_NAME || ')' || ' ON ' || REC.OWNER ||'.'|| REC.TABLENAME || ' TO ' || P_USERNAME2 || ';');
					ELSE
						DBMS_OUTPUT.PUT_LINE('GRANT ' || REC.PRIVILEGE || ' ON ' || REC.OWNER ||'.'|| REC.TABLENAME || ' TO ' || P_USERNAME2 || ';');
					END IF;
				END IF;
				
			END;
		END LOOP;		
		
	EXCEPTION
	WHEN OTHERS THEN
		RAISE_APPLICATION_ERROR(-20001,'AN ERROR WAS ENCOUNTERED - '||SQLCODE||' -ERROR- '||SQLERRM);
END;
/
SQL> set serveroutput on
SQL>
SQL> exec ASSIGNMENT2('USER_APP','SAMAD');
GRANT INSERT ON HR.EMPLOYEES TO SAMAD;
GRANT SELECT ON HR.EMPLOYEES TO SAMAD;
GRANT SELECT ON HR.JOB_HISTORY TO SAMAD;

PL/SQL procedure successfully completed.