Native method to pull out metadata about packages, procedures and functions? - oracle

I wish to be able to query Oracle for a list of public procedures and functions that belong to a package, something along the lines of:
select procedure_name from all_package_procedures where package_name = :my_package_name;
I also wish to be able to query Oracle for a list of parameters for a given procedure or function, something along the lines of:
select parameter_name, in_or_out, parameter_type from all_function_parameters where function_name = :my_function_name;
Is this possible natively? If not, does anyone know of existing code to achieve this?

You can query USER_OBJECTS & USER_PROCEDURES to get a list of all procedures & functions belonging to a particular package
SELECT procedure_name
FROM user_procedures
WHERE object_id = (SELECT object_id
FROM user_objects
WHERE object_name = '<YOUR-PACKAGE-NAME>'
AND object_type = 'PACKAGE')
Replace user_objects & user_procedures with all_objects & all_procedures respectively to fetch packages & procedures owned by other users.
I also wish to be able to query Oracle for a list of parameters for a given procedure or function,
For this, you can query user_arguments or all_arguments to fetch parameters of on object owned by the current user & all users respectively
SELECT argument_name,
data_type
FROM user_arguments
WHERE package_name = '<name-of-your-package-procedure-function>'

My own answer, derived from Sathyas, for the reference of others. Here is a single query to pull out a denormalized result of all procedures and their arguments for a given package:
select p.procedure_name
, a.argument_name
, a.data_type
, a.defaulted
, a.default_value
, a.in_out
, a.position
from all_procedures p
inner join all_objects o
on o.object_id = p.object_id
inner join all_arguments a
on a.package_name = o.object_name
and a.object_name = p.procedure_name
where o.object_type = 'PACKAGE'
and o.object_name = 'PACKAGE_NAME'
order by p.procedure_name, a.position;

Related

Retrieve argument details defined in private function/procedure [duplicate]

I want to obtain a list with all private procedures/functions from a package body.
For public object it is easy but I have no idea how to do that for private objects.
The nature of private functions is that they are private. There are no data dictionary views which expose them by default. USER_PROCEDURES and USER_ARGUMENTS only show information for public procedures (the ones defined in a package spec0.
However, we can get information about them using PL/SCOPE, but doing so requires a little bit of additional effort:
SQL> alter session set plscope_settings='IDENTIFIERS:ALL';
SQL> alter package your_package compile body;
Now you can find your private program units with this query:
select ui.type, ui.name, ui.usage_id
from user_identifiers ui
where ui.object_name = 'YOUR_PACKAGE'
and ui.usage = 'DEFINITION'
and ui.type in ('PROCEDURE', 'FUNCTION')
minus
( select 'PROCEDURE', upr.procedure_name
from user_procedures upr
where upr.object_name = 'YOUR_PACKAGE'
union
select 'FUNCTION', uarg.object_name
from user_arguments uarg
where uarg.package_name = 'YOUR_PACKAGE'
and uarg.position = 0
);
To get the arguments of a private procedure plug the USAGE_ID from the previous query into this query:
select ui.name
, ui.type
, ui.usage_id
, ui2.type as param_datatype
from user_identifiers ui
left join user_identifiers ui2
on ui2.usage_context_id = ui.usage_id
where ui.object_name = 'YOUR_PACKAGE'
and ui.usage = 'DECLARATION'
and ui.usage_context_id = :private_proc_usage_id
/
This needs to be a left join because user_identifiers has datatype entries for scalar datatypes (character, number, date, clob) but not complex datatypes (xmltype, user-defined types).
We can get lots of information about procedures from PL/SCOPE, even though it is not as easy as querying USER_PROCEDURES or USER_ARGUMENTS (in fact, it is surprisingly clunky). Find out more. Be aware that PL/SCOPE data is stored on the SYSAUX tablespace, so don't get into hot water with your DBA!

To extract private arguments details from procedure and function in Oracle [duplicate]

I want to obtain a list with all private procedures/functions from a package body.
For public object it is easy but I have no idea how to do that for private objects.
The nature of private functions is that they are private. There are no data dictionary views which expose them by default. USER_PROCEDURES and USER_ARGUMENTS only show information for public procedures (the ones defined in a package spec0.
However, we can get information about them using PL/SCOPE, but doing so requires a little bit of additional effort:
SQL> alter session set plscope_settings='IDENTIFIERS:ALL';
SQL> alter package your_package compile body;
Now you can find your private program units with this query:
select ui.type, ui.name, ui.usage_id
from user_identifiers ui
where ui.object_name = 'YOUR_PACKAGE'
and ui.usage = 'DEFINITION'
and ui.type in ('PROCEDURE', 'FUNCTION')
minus
( select 'PROCEDURE', upr.procedure_name
from user_procedures upr
where upr.object_name = 'YOUR_PACKAGE'
union
select 'FUNCTION', uarg.object_name
from user_arguments uarg
where uarg.package_name = 'YOUR_PACKAGE'
and uarg.position = 0
);
To get the arguments of a private procedure plug the USAGE_ID from the previous query into this query:
select ui.name
, ui.type
, ui.usage_id
, ui2.type as param_datatype
from user_identifiers ui
left join user_identifiers ui2
on ui2.usage_context_id = ui.usage_id
where ui.object_name = 'YOUR_PACKAGE'
and ui.usage = 'DECLARATION'
and ui.usage_context_id = :private_proc_usage_id
/
This needs to be a left join because user_identifiers has datatype entries for scalar datatypes (character, number, date, clob) but not complex datatypes (xmltype, user-defined types).
We can get lots of information about procedures from PL/SCOPE, even though it is not as easy as querying USER_PROCEDURES or USER_ARGUMENTS (in fact, it is surprisingly clunky). Find out more. Be aware that PL/SCOPE data is stored on the SYSAUX tablespace, so don't get into hot water with your DBA!

Retreive a list of private procedures/functions from a package body

I want to obtain a list with all private procedures/functions from a package body.
For public object it is easy but I have no idea how to do that for private objects.
The nature of private functions is that they are private. There are no data dictionary views which expose them by default. USER_PROCEDURES and USER_ARGUMENTS only show information for public procedures (the ones defined in a package spec0.
However, we can get information about them using PL/SCOPE, but doing so requires a little bit of additional effort:
SQL> alter session set plscope_settings='IDENTIFIERS:ALL';
SQL> alter package your_package compile body;
Now you can find your private program units with this query:
select ui.type, ui.name, ui.usage_id
from user_identifiers ui
where ui.object_name = 'YOUR_PACKAGE'
and ui.usage = 'DEFINITION'
and ui.type in ('PROCEDURE', 'FUNCTION')
minus
( select 'PROCEDURE', upr.procedure_name
from user_procedures upr
where upr.object_name = 'YOUR_PACKAGE'
union
select 'FUNCTION', uarg.object_name
from user_arguments uarg
where uarg.package_name = 'YOUR_PACKAGE'
and uarg.position = 0
);
To get the arguments of a private procedure plug the USAGE_ID from the previous query into this query:
select ui.name
, ui.type
, ui.usage_id
, ui2.type as param_datatype
from user_identifiers ui
left join user_identifiers ui2
on ui2.usage_context_id = ui.usage_id
where ui.object_name = 'YOUR_PACKAGE'
and ui.usage = 'DECLARATION'
and ui.usage_context_id = :private_proc_usage_id
/
This needs to be a left join because user_identifiers has datatype entries for scalar datatypes (character, number, date, clob) but not complex datatypes (xmltype, user-defined types).
We can get lots of information about procedures from PL/SCOPE, even though it is not as easy as querying USER_PROCEDURES or USER_ARGUMENTS (in fact, it is surprisingly clunky). Find out more. Be aware that PL/SCOPE data is stored on the SYSAUX tablespace, so don't get into hot water with your DBA!

Finding sequences and triggers associated with an Oracle table

I have used this query to fetch the list of sequences belonging to an Oracle database user:
SELECT * FROM all_sequences x,all_tables B
WHERE x.sequence_owner=B.owner AND B.TABLE_NAME='my_table';
But that database user is having many more sequence also, so the query returns me all the sequence of the database user. Can anybody help me to find the particular sequence of my_table using query so that I can get the auto increment id in my application.
i want the query which fetch list of table of my database user with the sequence and triggers used in the table
You can get the triggers associated with your tables from the user_triggers view. You can then look for any dependencies recorded for those triggers in user_dependencies, which may include objects other than sequences (packages etc.), so joining those dependencies to the user_sequences view will only show you the ones you are interested in.
Something like this, assuming you are looking at your own schema, and you're only interesting in triggers that references sequences (which aren't necessarily doing 'auto increment', but are likely to be):
select tabs.table_name,
trigs.trigger_name,
seqs.sequence_name
from user_tables tabs
join user_triggers trigs
on trigs.table_name = tabs.table_name
join user_dependencies deps
on deps.name = trigs.trigger_name
join user_sequences seqs
on seqs.sequence_name = deps.referenced_name;
SQL Fiddle demo.
If you're actually looking at a different schema then you'll need to use all_tables etc. and filter and join on the owner column for the user you're looking for. And if you want to include tables which don't have triggers, or triggers which don't refer to sequences, you can use outer joins.
Version looking for a different schema, though this assumes you have the privs necessary to access the data dictionary information - that the tables etc. are visible to you, which they may not be:
select tabs.table_name,
trigs.trigger_name,
seqs.sequence_name
from all_tables tabs
join all_triggers trigs
on trigs.table_owner = tabs.owner
and trigs.table_name = tabs.table_name
join all_dependencies deps
on deps.owner = trigs.owner
and deps.name = trigs.trigger_name
join all_sequences seqs
on seqs.sequence_owner = deps.referenced_owner
and seqs.sequence_name = deps.referenced_name
where tabs.owner = '<owner>';
If that can't see them then you might need to look at the DBA views, again if you have sufficient privs:
select tabs.table_name,
trigs.trigger_name,
seqs.sequence_name
from dba_tables tabs
join dba_triggers trigs
on trigs.table_owner = tabs.owner
and trigs.table_name = tabs.table_name
join dba_dependencies deps
on deps.owner = trigs.owner
and deps.name = trigs.trigger_name
join dba_sequences seqs
on seqs.sequence_owner = deps.referenced_owner
and seqs.sequence_name = deps.referenced_name
where tabs.owner = '<owner>';
One way would be to run these queries to check if there are any sequence's Pseudocolumns (NEXTVAL and CURRVAL ) used in your functions , procedures, packages, Triggers or PL/SQL JAVA SOURCE.
select * from user_source where
UPPER(TEXT) LIKE '%NEXTVAL%';
select * from all_source where
UPPER(TEXT) LIKE '%NEXTVAL%';
Then go to the specific Procedure, Function or Trigger to check which column/table gets populated by a sequence.
The query could also be used with '%CURRVAL%'
This might not help if you are running inserts from JDBC or other external applications using a sequence.
Oracle 12c introduced the IDENTITY columns, using which you could create a table with an identity column, which is generated by default.
CREATE TABLE t1 (c1 NUMBER GENERATED BY DEFAULT ON NULL AS IDENTITY,
c2 VARCHAR2(10));
This will internally create a sequence that auto-generates the value for the table's column.So, If you would like to know which sequence generates the value for which table, you may query the all_tab_columns
SELECT data_default AS sequence_val
,table_name
,column_name
FROM all_tab_columns
WHERE OWNER = 'HR'
AND identity_column = 'YES';
SEQUENCE_VAL |TABLE_NAME |COLUMN_NAME
-----------------------------------------|-------------------------------------
"HR"."ISEQ$$_78160".nextval |T1 |C1
I found a solution to this problem to guess the sequence of a particular sequence
select * from SYS.ALL_SEQUENCES where SEQUENCE_OWNER='OWNER_NAME' and LAST_NUMBER between (select max(FIELD_NAME) from TABLE_NAME) and (select max(FIELD_NAME)+40 from TABLE_NAME);
This query will guess by search the LAST_NUMBER of the sequence value between MAX value of the field using sequence and Max value + 40 (in my case cache value is 20, so I put 40)
select SEQUENCE_NAME from sys.ALL_TAB_IDENTITY_COLS where owner = 'SCHEMA_NAME' and table_name = 'TABLE_NAME';

How do I differentiate between Procedures and Functions in Oracle's Metadata?

I want to list all the Stored Procedures which use overloading in a given schema. All the procedures are within packages. I can use the SQL below to nearly get there (anything with proc_count > 1).
select
object_name, procedure_name, count(procedure_name) as proc_count
from
all_procedures
where
owner = 'SCHEMA_NAME'
group by
object_name, procedure_name
order by proc_count desc
However there seems to be no way to differentiate between a function named 'ask_version' and a procedure named 'ask_version' which I need to do in my case. The case being that our middleware has trouble calling procs where overloading is used. I need to do an impact analysis on how many places this occurs. We never call functions directly, hence the need to isolate them
Is there something that I'm missing?
all_arguments seems to help. For a function, there is an argument with position=0 (which is the return value), for procedures this argument does not exist.
SELECT object_name, procedure_name, t, COUNT(1) AS proc_count
FROM
(
SELECT p.object_name, p.procedure_name,
CASE WHEN a.object_id IS NULL THEN 'PROCEDURE' ELSE 'FUNCTION' END AS t
FROM all_procedures p
LEFT JOIN all_arguments a ON ( a.object_id = p.object_id
AND a.subprogram_id = p.subprogram_id AND a.position = 0 )
WHERE p.owner = 'SCHEMA_NAME'
)
GROUP BY object_name, procedure_name, t
ORDER BY proc_count DESC;
This is a bit tricky since Oracle stores packages as discrete objects from standalone functions and procedures.
The only easy way you can tell this is by looking at the argument metadata in ALL_ARGUMENTS. Functions have an argument at position 0 to specify the return type, whereas procedures do not.
Also, it's easy to tell if a function or procedure has overloads by checking the OVERLOAD field.
select P.OBJECT_NAME
, P.PROCEDURE_NAME
, DECODE(min(a.POSITION), 0, 'Function', 'Procedure') FUNC_OR_PROC
, DECODE(NVL(min(P.OVERLOAD), 0), 0, 'No', 'Yes') OVERLOADED
from ALL_PROCEDURES P
, ALL_ARGUMENTS a
where P.OWNER = 'FLOWS_030000'
and P.OBJECT_NAME = a.PACKAGE_NAME
and P.PROCEDURE_NAME = a.OBJECT_NAME
group by P.OBJECT_NAME, P.PROCEDURE_NAME
order by 1,2;

Resources