On a database project with the multiple team members doing the development work, it becomes harder to keep track of all the grants given. Before promoting your changes to the higher environments like UAT, TEST or production, you can use the following script to extract the grants on all the database objects in a schema.
SQL> select 'grant ' || privilege || ' on ' || table_name ||
2 ' to ' || grantee ||
3 case when grantable = 'YES' then ' with grant option;'
4 else ';'
5 end as my_grant
6 from user_tab_privs_made
7 order by table_name;
MY_GRANT
-----------------------------------------------------------------------------
grant ALTER on BONUS to SYSTEM;
grant SELECT on DEPT to SCOTT;
grant INSERT on EMP to SCOTT;
grant SELECT on EMP to SCOTT;
grant UPDATE on EMP to SCOTT;
grant REFERENCES on EMP to SCOTT;
grant ON COMMIT REFRESH on EMP to SCOTT;
grant QUERY REWRITE on EMP to SCOTT;
grant DEBUG on EMP to SCOTT;
grant FLASHBACK on EMP to SCOTT;
grant INDEX on EMP to SCOTT;
grant ALTER on EMP to SCOTT;
grant DELETE on EMP to SCOTT;
grant SELECT on EMP to SYSTEM with grant option;
grant EXECUTE on P to HR;
15 rows selected.
Please notice the "with grant option" in the above query result. Also, notice that the procedure grants are also included there. In fact, all the grants will be included here.
The dbms_metadata is not a good idea to use for the grants. The above approach always works!
If you want to get the object grants for more than one schema, use the following version of the query.
SQL> select 'grant ' || privilege || ' on ' || owner || '.' || table_name ||
2 ' to ' || grantee ||
3 case when grantable = 'YES' then ' with grant option;'
4 else ';'
5 end as my_grant
6 from dba_tab_privs
7 where owner in ('SCOTT','HR')
8 order by owner,table_name;
MY_GRANT
---------------------------------------------------------------------------------------
grant SELECT on SCOTT.BONUS to HR;
grant UPDATE on SCOTT.BONUS to HR;
grant INSERT on SCOTT.BONUS to HR;
grant ON COMMIT REFRESH on SCOTT.DEPT to PUBLIC;
grant REFERENCES on SCOTT.DEPT to PUBLIC;
grant UPDATE on SCOTT.DEPT to PUBLIC;
grant SELECT on SCOTT.DEPT to PUBLIC;
grant INSERT on SCOTT.DEPT to PUBLIC;
grant INDEX on SCOTT.DEPT to PUBLIC;
grant DELETE on SCOTT.DEPT to PUBLIC;
grant ALTER on SCOTT.DEPT to PUBLIC;
grant QUERY REWRITE on SCOTT.DEPT to PUBLIC;
grant DEBUG on SCOTT.DEPT to PUBLIC;
grant FLASHBACK on SCOTT.DEPT to PUBLIC;
grant UPDATE on SCOTT.DEPT to HR;
grant INSERT on SCOTT.DEPT to HR;
grant SELECT on SCOTT.DEPT to HR;
grant SELECT on SCOTT.LINEITEM to HR;
grant UPDATE on SCOTT.LINEITEM to HR;
grant INSERT on SCOTT.LINEITEM to HR;
grant SELECT on SCOTT.ORDERS to HR;
grant UPDATE on SCOTT.ORDERS to HR;
grant INSERT on SCOTT.ORDERS to HR;
grant UPDATE on SCOTT.PROJ to HR;
grant SELECT on SCOTT.PROJ to HR;
grant INSERT on SCOTT.PROJ to HR;
grant SELECT on SCOTT.SALGRADE to HR;
grant UPDATE on SCOTT.SALGRADE to HR;
grant INSERT on SCOTT.SALGRADE to HR;
29 rows selected.
Please note that we are using "dba_tab_privs" view now and also prefixing the object name with the owner.
Please let me know your feedback!
Thanks
If you are interested in the book "Oracle SQL Scipting". here is the link.
http://www.amazon.com/Oracle-SQL-Scripting-ebook/dp/B00E2T1DVA/ref=sr_1_1?ie=UTF8&qid=1374436123&sr=8-1&keywords=oracle+sql+scripting
dbms_metadata.get_ddl extract Oracle DDL Oracle SQL Script dbms_metadata.get_ddl index dbms_metadata.get_ddl materialized view
Showing posts with label dbms_metadata. Show all posts
Showing posts with label dbms_metadata. Show all posts
Saturday, October 6, 2012
Saturday, September 1, 2012
dbms_metadata
Oracle scripting can be used to extract DDL for database objects. The most common use is for getting the DDL for tables.
Here is a simple demo.
SQL> col my_ddl format a100 word_wrap
SQL> set long 50000
SQL> set pagesize 0
SQL>
SQL> select dbms_metadata.get_ddl('TABLE',table_name,user) AS my_ddl
2 from all_tables where owner = 'SCOTT'
3 and table_name = 'DEPT';
CREATE TABLE "SCOTT"."DEPT"
( "DEPTNO" NUMBER(2,0),
"DNAME" CHAR(14),
"LOC" CHAR(13),
CONSTRAINT "DEPT_DEPTNO_PK" PRIMARY KEY ("DEPTNO")
USING INDEX PCTFREE 10 INITRANS 2 MAXTRANS 255 COMPUTE STATISTICS
STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT FLASH_CACHE
DEFAULT CELL_FLASH_CACHE DEFAULT)
TABLESPACE "USERS" ENABLE
) SEGMENT CREATION IMMEDIATE
PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 NOCOMPRESS LOGGING
STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT FLASH_CACHE
DEFAULT CELL_FLASH_CACHE DEFAULT)
TABLESPACE "USERS"
The above output needs some revision.
Let's get rid of the storage clause.
SQL> EXECUTE DBMS_METADATA.SET_TRANSFORM_PARAM(DBMS_METADATA.SESSION_TRANSFORM,'STORAGE',false);
PL/SQL procedure successfully completed.
SQL> /
CREATE TABLE "SCOTT"."DEPT"
( "DEPTNO" NUMBER(2,0),
"DNAME" CHAR(14),
"LOC" CHAR(13),
CONSTRAINT "DEPT_DEPTNO_PK" PRIMARY KEY ("DEPTNO")
USING INDEX PCTFREE 10 INITRANS 2 MAXTRANS 255 COMPUTE STATISTICS
TABLESPACE "USERS" ENABLE
) SEGMENT CREATION IMMEDIATE
PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 NOCOMPRESS LOGGING
TABLESPACE "USERS"
We also want to get rid of segment attributes, put a semicolon at the end as sql terminator and make the output pretty!
SQL> EXECUTE DBMS_METADATA.SET_TRANSFORM_PARAM(DBMS_METADATA.SESSION_TRANSFORM,'SEGMENT_ATTRIBUTES',false);
PL/SQL procedure successfully completed.
SQL> EXECUTE DBMS_METADATA.SET_TRANSFORM_PARAM(DBMS_METADATA.SESSION_TRANSFORM,'SQLTERMINATOR',true);
PL/SQL procedure successfully completed.
SQL> EXECUTE DBMS_METADATA.SET_TRANSFORM_PARAM(DBMS_METADATA.SESSION_TRANSFORM,'PRETTY',true);
PL/SQL procedure successfully completed.
SQL> /
CREATE TABLE "SCOTT"."DEPT"
( "DEPTNO" NUMBER(2,0),
"DNAME" CHAR(14),
"LOC" CHAR(13),
CONSTRAINT "DEPT_DEPTNO_PK" PRIMARY KEY ("DEPTNO") ENABLE
) ;
Now, the output looks little better!
If we want to get the DDL for all the tables in the schema, let's remove the table_name filter.
SQL> select dbms_metadata.get_ddl('TABLE',table_name,user) AS my_ddl
2 from all_tables where owner = 'SCOTT';
CREATE TABLE "SCOTT"."EMP"
( "EMPNO" NUMBER(4,0) NOT NULL ENABLE,
"ENAME" CHAR(10),
"JOB" CHAR(9),
"MGR" NUMBER(4,0),
"HIREDATE" DATE,
"SAL" NUMBER(7,2),
"COMM" NUMBER(7,2),
"DEPTNO" NUMBER(2,0),
"PROJNO" NUMBER,
"LOADSEQ" NUMBER,
CONSTRAINT "EMP_DEPTNO_FK" FOREIGN KEY ("DEPTNO")
REFERENCES "SCOTT"."DEPT" ("DEPTNO") ENABLE
) ;
CREATE TABLE "SCOTT"."SALGRADE"
( "GRADE" NUMBER,
"LOSAL" NUMBER,
"HISAL" NUMBER
) ;
CREATE TABLE "SCOTT"."DEPT"
( "DEPTNO" NUMBER(2,0),
"DNAME" CHAR(14),
"LOC" CHAR(13),
CONSTRAINT "DEPT_DEPTNO_PK" PRIMARY KEY ("DEPTNO") ENABLE
) ;
Looks good? Well, the only catch is, the table creation script may not be in the right order. In the above case, we want the dept table to be created first and then emp table. Otherwise, we are going to get error.
We will try to figure out how to achieve that in the next post!
Meanwhile, if you have a better idea, please weigh in!
==========================================================
If you are interested in the book "Oracle SQL Scipting". here is the link.
http://www.amazon.com/Oracle-SQL-Scripting-ebook/dp/B00E2T1DVA/ref=sr_1_1?ie=UTF8&qid=1374436123&sr=8-1&keywords=oracle+sql+scripting
Here is a simple demo.
SQL> col my_ddl format a100 word_wrap
SQL> set long 50000
SQL> set pagesize 0
SQL>
SQL> select dbms_metadata.get_ddl('TABLE',table_name,user) AS my_ddl
2 from all_tables where owner = 'SCOTT'
3 and table_name = 'DEPT';
CREATE TABLE "SCOTT"."DEPT"
( "DEPTNO" NUMBER(2,0),
"DNAME" CHAR(14),
"LOC" CHAR(13),
CONSTRAINT "DEPT_DEPTNO_PK" PRIMARY KEY ("DEPTNO")
USING INDEX PCTFREE 10 INITRANS 2 MAXTRANS 255 COMPUTE STATISTICS
STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT FLASH_CACHE
DEFAULT CELL_FLASH_CACHE DEFAULT)
TABLESPACE "USERS" ENABLE
) SEGMENT CREATION IMMEDIATE
PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 NOCOMPRESS LOGGING
STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT FLASH_CACHE
DEFAULT CELL_FLASH_CACHE DEFAULT)
TABLESPACE "USERS"
The above output needs some revision.
Let's get rid of the storage clause.
SQL> EXECUTE DBMS_METADATA.SET_TRANSFORM_PARAM(DBMS_METADATA.SESSION_TRANSFORM,'STORAGE',false);
PL/SQL procedure successfully completed.
SQL> /
CREATE TABLE "SCOTT"."DEPT"
( "DEPTNO" NUMBER(2,0),
"DNAME" CHAR(14),
"LOC" CHAR(13),
CONSTRAINT "DEPT_DEPTNO_PK" PRIMARY KEY ("DEPTNO")
USING INDEX PCTFREE 10 INITRANS 2 MAXTRANS 255 COMPUTE STATISTICS
TABLESPACE "USERS" ENABLE
) SEGMENT CREATION IMMEDIATE
PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 NOCOMPRESS LOGGING
TABLESPACE "USERS"
We also want to get rid of segment attributes, put a semicolon at the end as sql terminator and make the output pretty!
SQL> EXECUTE DBMS_METADATA.SET_TRANSFORM_PARAM(DBMS_METADATA.SESSION_TRANSFORM,'SEGMENT_ATTRIBUTES',false);
PL/SQL procedure successfully completed.
SQL> EXECUTE DBMS_METADATA.SET_TRANSFORM_PARAM(DBMS_METADATA.SESSION_TRANSFORM,'SQLTERMINATOR',true);
PL/SQL procedure successfully completed.
SQL> EXECUTE DBMS_METADATA.SET_TRANSFORM_PARAM(DBMS_METADATA.SESSION_TRANSFORM,'PRETTY',true);
PL/SQL procedure successfully completed.
SQL> /
CREATE TABLE "SCOTT"."DEPT"
( "DEPTNO" NUMBER(2,0),
"DNAME" CHAR(14),
"LOC" CHAR(13),
CONSTRAINT "DEPT_DEPTNO_PK" PRIMARY KEY ("DEPTNO") ENABLE
) ;
Now, the output looks little better!
If we want to get the DDL for all the tables in the schema, let's remove the table_name filter.
SQL> select dbms_metadata.get_ddl('TABLE',table_name,user) AS my_ddl
2 from all_tables where owner = 'SCOTT';
CREATE TABLE "SCOTT"."EMP"
( "EMPNO" NUMBER(4,0) NOT NULL ENABLE,
"ENAME" CHAR(10),
"JOB" CHAR(9),
"MGR" NUMBER(4,0),
"HIREDATE" DATE,
"SAL" NUMBER(7,2),
"COMM" NUMBER(7,2),
"DEPTNO" NUMBER(2,0),
"PROJNO" NUMBER,
"LOADSEQ" NUMBER,
CONSTRAINT "EMP_DEPTNO_FK" FOREIGN KEY ("DEPTNO")
REFERENCES "SCOTT"."DEPT" ("DEPTNO") ENABLE
) ;
CREATE TABLE "SCOTT"."SALGRADE"
( "GRADE" NUMBER,
"LOSAL" NUMBER,
"HISAL" NUMBER
) ;
CREATE TABLE "SCOTT"."DEPT"
( "DEPTNO" NUMBER(2,0),
"DNAME" CHAR(14),
"LOC" CHAR(13),
CONSTRAINT "DEPT_DEPTNO_PK" PRIMARY KEY ("DEPTNO") ENABLE
) ;
Looks good? Well, the only catch is, the table creation script may not be in the right order. In the above case, we want the dept table to be created first and then emp table. Otherwise, we are going to get error.
We will try to figure out how to achieve that in the next post!
Meanwhile, if you have a better idea, please weigh in!
==========================================================
If you are interested in the book "Oracle SQL Scipting". here is the link.
http://www.amazon.com/Oracle-SQL-Scripting-ebook/dp/B00E2T1DVA/ref=sr_1_1?ie=UTF8&qid=1374436123&sr=8-1&keywords=oracle+sql+scripting
Subscribe to:
Posts (Atom)