Oracle's dbms_metadata.get_ddl for object_type JOB - oracle

I'd like to create ddl scripts for most of my database objects. dbms_metadata.get_ddl works for most of the object types. For instance the following creates the ddl for a view:
select dbms_metadata.get_ddl ( 'VIEW', 'SAMPLE_VIEW') from dual
On the other hand it's not working for object_type 'JOB'. The following:
select dbms_metadata.get_ddl( 'JOB', 'SAMPLE_JOB' ) from dual
gives the following error:
ORA-31604: invalid NAME parameter "NAME" for object type JOB in function SET_FILTER
ORA-06512: at "SYS.DBMS_SYS_ERROR", line 116
ORA-06512: at "SYS.DBMS_METADATA_INT", line 4705
ORA-06512: at "SYS.DBMS_METADATA_INT", line 8582
ORA-06512: at "SYS.DBMS_METADATA", line 2882
ORA-06512: at "SYS.DBMS_METADATA", line 2748
ORA-06512: at "SYS.DBMS_METADATA", line 4333
ORA-06512: at line 1
If I list my jobs using
select * from user_objects where object_type='JOB'
it shows SAMPLE_JOB (just like it shows SAMPLE_VIEW if filtered for object_type='VIEW').
Why is it working for VIEW (and TABLE, INDEX, TRIGGER, ...) and not for JOB?
I'm using Oracle 10g.

select dbms_metadata.get_ddl('PROCOBJ', 'yourJobNameGoesHere') from dual;
PROCOBJ's are procedural objects.

select dbms_metadata.get_ddl('PROCOBJ',['JOB'|'PROGRAM'|'SCHEDULE'],'OWNER') from dual;
The PROCOBJ can be JOB, PROGRAM and SCHEDULE.

Alternative, get all jobs from the database with their DDL:
select owner, job_name, dbms_metadata.get_ddl('PROCOBJ', job_name, owner) as ddl_output from ALL_SCHEDULER_JOBS

Even I tried all above to get DDL in Oracle version 10g, but no success.
Here is what I figure out to get the detail of the job:
set pages 200 lines 200
col owner format a20
col job_name format a25
col JOB_ACTION format a75
col COMMENTS format a60
select owner, job_name, next_run_date, state, enabled from dba_scheduler_jobs where job_name like '%AUDIT%';
-- get the detail of scheduled jobs.
select OWNER,JOB_NAME, JOB_ACTION, COMMENTS FROM DBA_SCHEDULER_JOBS where JOB_NAME='PURGE_AUDIT_LOG';
-- get the limited detail from the selected column.
select * FROM DBA_SCHEDULER_JOBS where JOB_NAME='PURGE_AUDIT_LOG';
-- to get the complete detail of a specific job along with code and other details.

Related

Query to check the full schema scan for tables in Oracle DB

Hi I have a requirement to scan through the schema and identify the tables which are redundant (candidate for dropping) ,so i did a select in DBA_Dependencies to check whether the tables are being used in any of the DB object types like (Procedure, package body, views, Materialized views....) i was able to find some tables and excluded the tables ,since i also need to capture the total counts, when the table was last loaded/used is there a automated way to select only selected tables (not found in dependencies list) and capture the counts and also when it was used/loaded
Difficulty - so many tables 500+
i have used the below query
Query 1
select table_name,
to_number(extractvalue(xmltype(dbms_xmlgen.getxml('select count(*) c from '||owner||'.'||table_name)),'/ROWSET/ROW/C')) as count
from all_tables
where owner = 'SCHEMA_NAME'
Query 2
select owner, table_name, num_rows, sample_size, last_analyzed from all_tables;
Query 1 Result
Filter Table_name=CUST_ORDER
OWNER TABLE_NAME COUNT SAMPLE_SIZE LAST_ANALYZED
ABCD CUST_ORDER 1083 1023 01.01.2020
Query 2 Result
Filter Table_name=CUST_ORDER
OWNER TABLE_NAME NUM_ROWS SAMPLE_SIZE LAST_ANALYZED
ABCD CUST_ORDER 1023 1023 01.01.2020
Question
Query 1 - Results not matching when compared with query 2 ,since the same table and filter is applied
in both the queries and why the results are not matching ?
but when i randomly checked other filter it is matching , does any one know the reason ?
Upon further testing i encountered an error ,what does this error signify permissions ?
ORA-29913: error in executing ODCIEXTTABLEOPEN callout
ORA-29400: data cartridge error
KUP-04040: file **-**.csv in ****_***_***_***** not found
29913. 00000 - "error in executing %s callout"
*Cause: The execution of the specified callout caused an error.
*Action: Examine the error messages take appropriate action.
The number you see on all_tables is a point in time capture of the number of rows. It will only be updated if the statistics are rebuilt for that table.
Here is an example:
CREATE TABLE t1 AS
SELECT *
FROM all_objects;
SELECT t.num_rows
FROM all_tables t
WHERE t.table_name = 'T1';
-- 78570
SELECT COUNT(*)
FROM t1;
-- 78570
The stats and the physical number of rows match!
INSERT INTO t1
SELECT *
FROM all_objects ao
WHERE rownum <= 5;
-- 5 rows inserted
SELECT t.num_rows
FROM all_tables t
WHERE t.table_name = 'T1';
-- 78570
SELECT COUNT(*)
FROM t1;
-- 78575
Here we have the mis-match because rows were inserted (or maybe even deleted), but the stats for the table have not been updated. Let's update them:
BEGIN
dbms_stats.gather_table_stats(ownname => 'SCHEMA',
tabname => 'T1');
END;
/
SELECT t.num_rows
FROM all_tables t
WHERE t.table_name = 'T1';
-- 78575
Now you can see the rows match. Using the value from all_tables may be good enough for your research (and will certainly be faster to query than counting every table).
Query - 1 is actual data of the table and hence it is accurate data. One can rely on this query's output.
Query - 2 is not actual data. It is the data captured when table was last analyzed and one should not be dependant on this query for finding number of records in the table.
You can gather the stats on this table and execute the query-2 then you will find the same data as query-1
If records are not inserted or deleted from the table after stats are gathered, then query-1 and query-2 data will match for that table.

How can i get partitioned script using get_ddl?

I am using Oracle 12c as database and getting ddl of table or other objects using :-
dbms_metadata.get_ddl('TABLE','TABLE_NAME','SCHEMA_NAME');
Same as for constraints and reference constraint i am using :-
dbms_metadata.get_dependent_ddl('CONSTRAINT','TABLE_NAME','SCHEMA_NAME');
dbms_metadata.get_dependent_ddl('REF_CONSTRAINT','TABLE_NAME','SCHEMA_NAME');
Now my problem is i want to extract partition script from table and i tried following :-
select dbms_metadata.get_dependent_ddl('PARTITIONING','TABLE_NAME','SCHEMA_NAME') from dual;
but its giving the following error :-
ORA-31600: invalid input value PARTITIONING for parameter OBJECT_TYPE in function GET_DEPENDENT_DDL
ORA-06512: at "SYS.DBMS_METADATA", line 6069
ORA-06512: at "SYS.DBMS_METADATA", line 8761
ORA-06512: at line 1
31600. 00000 - "invalid input value %s for parameter %s in function %s"
*Cause: A NULL or invalid value was supplied for the parameter.
*Action: Correct the input value and try the call again.
I have also tried :-
select dbms_metadata.get_ddl('PARTITION','PARTITION_NAME','SECONDARYUSER') from dual;
but its giving same error.
Please suggest how can i get partitioned ddl using get_ddl method in oracle.
Partitioning is a table option, not a separate object. By default, GET_DDL for a table should produce the partitioning information. If it doesn't, it's possible you have a session transformation that's disabling it. These two statements should definitely generate a DDL script that includes all the partitioning options:
begin
dbms_metadata.set_transform_param(dbms_metadata.session_transform,'PARTITIONING',true);
end;
/
select dbms_metadata.get_ddl('TABLE','TABLE_NAME','SCHEMA_NAME') from dual;
If you're looking for a way to automatically generate a script that converts a table from nonpartitioned to partitioned, I'm afraid you're out of luck. Although 12c has the ability to convert tables with ALTER TABLE, the package DBMS_METADATA_DIFF apparently has not yet been updated to understand those commands.
For example, if you create the same table with and without partitions, this script doesn't work:
select dbms_metadata_diff.compare_alter(object_type => 'TABLE', name1 => 'TABLE2', name2 => 'TABLE1') diffs from dual;
DIFFS
--------------------------------------------------------------
-- ORA-39266: Cannot alter unpartitioned table to partitioned.
ALTER TABLE "JHELLER"."TABLE2" RENAME TO "TABLE1"
Luckily, in some cases the ALTER syntax seems easy. In my simple examples, I could change a table to partitioned with a command like this:
alter table unpartitioned_table modify
[partitioning clause]
online;
Try this to filter transformation option :-
BEGIN
DBMS_METADATA.set_transform_param (DBMS_METADATA.session_transform, 'SQLTERMINATOR', true);
DBMS_METADATA.set_transform_param (DBMS_METADATA.session_transform, 'PRETTY', true);
DBMS_METADATA.set_transform_param (DBMS_METADATA.session_transform, 'SEGMENT_ATTRIBUTES', false);
DBMS_METADATA.set_transform_param (DBMS_METADATA.session_transform, 'STORAGE', false);
END;
/
SELECT DBMS_METADATA.get_ddl ('TABLE', table_name, owner)
FROM all_tables
WHERE owner = UPPER('REFDATA')
AND table_name = DECODE(UPPER('<TBL_NM>'), 'ALL', table_name, UPPER('<TBL_NM>'));
This should give only the default partition along with table ddl.

Incorrect output while using dictionary tables inside Trigger

I am using ALL_TABLES/ALL_TAB_COLUMNS to get count of tables in my schema (EDW_SRC) and another schema(EDW_STG). I get correct counts when i run the query in my sql developer as shown below. But if i put the same query inside a trigger, i get wrong count for other schema(EDW_STG).
Please refer below code:
(This is just a sample code to replicate the issue, not my business requirement. I am referring ALL_TAB_COLUMNS in my actual code to get the number of columns in a particular table in different schema, for which i have Select access.)
select user from dual;
USER
-----
EDW_SRC
DROP TABLE ABC;
Table ABC dropped.
CREATE TABLE ABC(ID NUMBER);
Table ABC created.
select count(1) EDW_STG_CNT
from all_tables
where owner='EDW_STG';--Different Schema
EDW_STG_CNT
----------
101
select count(1) EDW_SRC_CNT
from all_tables
where owner='EDW_SRC';--My Schema
EDW_SRC_CNT
------------
1554
create or replace trigger trig_test_dml_abc
before insert on abc
DECLARE
V_STG_CNT number :=NULL;
V_SRC_CNT number :=NULL;
begin
DBMS_OUTPUT.PUT_LINE('***** TRIGGER OUTPUT *****');
select count(1) into V_SRC_CNT from all_tables
where owner='EDW_SRC'; --My Schema
DBMS_OUTPUT.PUT_LINE('My Schema EDW_SRC_CNT :'||V_SRC_CNT);
select count(1) into V_STG_CNT from all_tables
where owner='EDW_STG'; --Different Schema
DBMS_OUTPUT.PUT_LINE('Different Schema EDW_STG_CNT :'||V_STG_CNT);
end;
Trigger TRIG_TEST_DML_ABC compiled
INSERT INTO ABC VALUES (2);
1 row inserted.
***** TRIGGER OUTPUT *****
My Schema EDW_SRC_CNT :1554
Different Schema EDW_STG_CNT :2
The Different Schema count should be 101. Why is it coming as 2.
Oracle Version:
Oracle Database 11g Enterprise Edition Release 11.2.0.4.0 - 64bit Production
Thanks
K

SELECT a table from oracle data dictionary

I am new to SQL and recently installed Oracle 11g. I read the post here on selecting all tables from user_tables. I'm trying to select a specific table and following some of the suggestions in the post does not appear to work.
The following executes fine and returns all tables available to me including a table named faculty_t:
select * from user_tables;
select * from dba_tables;
select * from all_tables;
desc faculty_t;
But I get error when I do the following:
select * from user_tables where table_name = FACULTY_T;
The first set of statements confirm that I do have a table named faculty_t. However, trying to select this table from user_tables, all_tables, or dba_tables does not appear to work for me right now. The error message reads something like:
ORA-00904: "FACULTY_T": invalid identifier
00904. 00000 - "%s: invalid identifier"
*Cause:
*Action:
Error at Line: 208 Column: 8
Any thoughts? Thanks!
String literals in SQL are wrapped in '. So:
select * from user_tables where table_name = 'FACULTY_T';
When you did a desc faculty_t, the SQL engine knew that a table name was expected at that spot (the syntax expects a table name there). But in your select query, sql is just looking for the value of a column that happens to have a string data type, so you need to use the ' for a string literal.

Efficient way to obtain DDL from entire Oracle DB

Currently there are about 30 tables in the Oracle 11.1 database.
Is there a way to generate all ddl with a single command? (Or a few commands?)
Edit:
Following a suggestion below, I tried:
SELECT dbms_metadata.get_ddl( 'TABLE', table_name, owner )
FROM all_tables;
And got:
ORA-31603: object "HS_PARTITION_COL_NAME" of type TABLE not found in schema "SYS"
ORA-06512: at "SYS.DBMS_SYS_ERROR", line 105
ORA-06512: at "SYS.DBMS_METADATA", line 3241
ORA-06512: at "SYS.DBMS_METADATA", line 4812
ORA-06512: at line 1
31603. 00000 - "object \"%s\" of type %s not found in schema \"%s\""
*Cause: The specified object was not found in the database.
*Action: Correct the object specification and try the call again.
It's clear that there is something extremely basic about dbms_metadata that I don't understand.
Here's what worked for me:
SELECT dbms_metadata.get_ddl('TABLE', table_name)
FROM user_tables;
You can use the DBMS_METADATA package. Something like
SELECT dbms_metadata.get_ddl( 'TABLE', table_name, owner )
FROM all_tables
WHERE <<some condition to get the 30 tables in question>>
Yes you can pretty easily using the dbms_metadata package. You can write a routine that opens a cursor on the USER_TABLES system table and gets the ddl for each table. An example for that is in the article too.
If you want to individually generate ddl for each object,
Queries are:
--GENERATE DDL FOR ALL USER OBJECTS
--1. FOR ALL TABLES
SELECT DBMS_METADATA.GET_DDL('TABLE', TABLE_NAME) FROM USER_TABLES;
--2. FOR ALL INDEXES
SELECT DBMS_METADATA.GET_DDL('INDEX', INDEX_NAME) FROM USER_INDEXES WHERE INDEX_TYPE ='NORMAL';
--3. FOR ALL VIEWS
SELECT DBMS_METADATA.GET_DDL('VIEW', VIEW_NAME) FROM USER_VIEWS;
OR
SELECT TEXT FROM USER_VIEWS
--4. FOR ALL MATERILIZED VIEWS
SELECT QUERY FROM USER_MVIEWS
--5. FOR ALL FUNCTION
SELECT DBMS_METADATA.GET_DDL('FUNCTION', OBJECT_NAME) FROM USER_PROCEDURES WHERE OBJECT_TYPE = 'FUNCTION'
GET_DDL Function doesnt support for some object_type like LOB,MATERIALIZED VIEW, TABLE PARTITION
SO, Consolidated query for generating DDL will be:
SELECT OBJECT_TYPE, OBJECT_NAME,DBMS_METADATA.GET_DDL(OBJECT_TYPE, OBJECT_NAME, OWNER) FROM ALL_OBJECTS WHERE (OWNER = 'XYZ') AND OBJECT_TYPE NOT IN('LOB','MATERIALIZED VIEW', 'TABLE PARTITION') ORDER BY OBJECT_TYPE, OBJECT_NAME;

Resources