3

I've been researching for how to describe TABLES and VIEWS without using 'DESCRIBE table/view;' clause. I found that it could be solved using something like:

SELECT column_name, data_type, data_length, data_precision, data_scale, nullable
FROM all_tab_columns
WHERE table_name = 'TABLE'

Which is perfectly programmable in a computer language like PHP, but I didn't found a workaround for 'DESCRIBE package_name' clause.

I have the following idea (yet in SQL*PLUS with a spool):

DECLARE
  x VARCHAR2(50);
  CURSOR cursorPaquetes IS
    SELECT DISTINCT OBJECT_NAME
    FROM ALL_OBJECTS
    WHERE OBJECT_TYPE = 'PACKAGE' AND OWNER = 'SATURN';
BEGIN
  FOR item IN cursorPaquetes LOOP
    x := 'DESCRIBE '||item.OBJECT_NAME||';';
    EXECUTE IMMEDIATE x;
  END LOOP;
END;

But it didn't work :(. Throws the following error:

ORA-00900: sentencia SQL no válida ORA-06512: en línea 12

And when modify the 'x' variable like this:

x := 'BEGIN DESCRIBE '||item.OBJECT_NAME||'; END;';

I get the following error:

ERROR en línea 1: ORA-06550: línea 1, columna 16: PLS-00103: Encountered the symbol "BVGKFDCS" when expecting one of the following: := . ( @ % ; The symbol ":=" was substituted for "BVGKFDCS" to continue. ORA-06512: en línea 12

Where "BVGKFDCS" is the name of one of the packages of my schema.

Thanks in advance.

P.D. I want to get something like that (but for each package):

DESCRIBE BVGKFDCS;

PROCEDURE P_GETPROFESSORS
 Nombre de Argumento            Tipo                    E/S   ¿Por Defecto?
 ------------------------------ ----------------------- ------ --------
 P_CAMP_IN                      VARCHAR2                IN
 P_COLL_IN                      VARCHAR2                IN
 P_DEPT_IN                      VARCHAR2                IN
 P_TERM_IN                      VARCHAR2                IN
PROCEDURE P_GETTERMSBYPROF
 Nombre de Argumento            Tipo                    E/S   ¿Por Defecto?
 ------------------------------ ----------------------- ------ --------
 NAME_ARRAY                     TABLE OF VARCHAR2(32000) IN
 VALUE_ARRAY                    TABLE OF VARCHAR2(32000) IN
PROCEDURE P_INIT
 Nombre de Argumento            Tipo                    E/S   ¿Por Defecto?
 ------------------------------ ----------------------- ------ --------
 PIDM                           VARCHAR2                IN
PROCEDURE P_OBTENER_VALOR
 Nombre de Argumento            Tipo                    E/S   ¿Por Defecto?
 ------------------------------ ----------------------- ------ --------

Note that this output is different from:

select * from user_source
akolmogorov
  • 33
  • 1
  • 6
  • 1
    possible duplicate of [Query to search all packages for table and/or column](http://stackoverflow.com/questions/4852993/query-to-search-all-packages-for-table-and-or-column) – T.S. May 06 '15 at 20:19
  • 1
    Hi, thanks for replay. No, this is not a duplicate because the DESCRIBE clause describes the parameter of all the procedures in such package. – akolmogorov May 06 '15 at 21:58
  • 1
    `DESCRIBE` or `DESC` is not a clause. It is a SQL*Plus command. – T.S. May 06 '15 at 22:42
  • answered here https://stackoverflow.com/a/45515580/1859096 – Andrey Khmelev Aug 04 '17 at 21:13

4 Answers4

5

Take a look at USER_PROCEDURES. I suspect this is what DESCRIBE queries when you use it on a package, procedure, or function.

EDIT: Sorry, also incorporate USER_ARGUMENTS to list the parameters for each subprogram. The logic to join the two views is not immediately obvious because of the ways different object types are handled. This query looks like it produces reasonable results but I have not checked the results carefully:

SELECT * FROM all_arguments A
JOIN all_procedures p
  ON ( ( p.object_type = 'PACKAGE' AND A.package_name = p.object_name AND A.object_name = p.procedure_name)
       OR
       ( p.object_type <> 'PACKAGE' AND A.package_name IS NULL AND A.object_name = p.object_name )
    )
  AND p.owner = A.owner
Dave Costa
  • 47,262
  • 8
  • 56
  • 72
2

You need to use User_Source, DBA_SOURCE or All_Source. All code is stored there.

select text 
from user_source
where name = 'procedure_name' 
order by line;

Type of object: FUNCTION, JAVA SOURCE, PACKAGE, PACKAGE BODY, PROCEDURE, TRIGGER, TYPE, TYPE BODY

T.S.
  • 18,195
  • 11
  • 58
  • 78
  • Hi, thanks for your answer. I don't have any procedure name, I just have the package name. – akolmogorov May 06 '15 at 22:02
  • 1
    @akolmogorov Then put your package name there. I think, I clearly posted what type of object can be queried that way – T.S. May 06 '15 at 22:41
  • Yes, you are right. You clearly posted what type of object can be required and you indicate also which tables could help for this workaround. Unfortunately none of the tables you suggested worked for me. It was the combination that @Dave Acosta suggested that work for me. Thank you very much for you patient and effort. Greetings from Mexico. – akolmogorov May 07 '15 at 17:01
0

describe doesn't work within execute immediate because it is a SQL*Plus command, rather than part of either a SQL or PL/SQL command. It is interpreted by the client, rather than the server.

The best way to get the source for any database object (including packages and package bodies), is DBA_SOURCE or USER_SOURCE, as suggested by @T.S..

There are data dictionary views for every kind of object in the database. When trying to get similar kinds of data for other object types, you should reference the dictionary view, which helpfully catalogs the data dictionary. As an example, the dictionary entry for user_source is:

TABLE_NAME  | COMMENTS
------------+------------------------------------------------
USER_SOURCE | Source of stored objects accessible to the user

The procedure names are part of the package specification. Querying all_source with the package name and type='package' will return the specification, including all of the public procedures and their parameters.

Allan
  • 17,141
  • 4
  • 52
  • 69
  • Thank you very much for your answer. I just realize doesn't will work with by the reasons you explain up there. The problem is that I didn't have the procedure names, indeed, that is precisely I want (plus the data types inputs and output of such procedures). – akolmogorov May 06 '15 at 22:17
-1

does this work for you?

SQL> SELECT DBMS_METADATA.GET_DDL('PACKAGE','EMP_PKG','SCOTT') FROM DUAL;

SQL> SELECT DBMS_METADATA.GET_DDL('PACKAGE_BODY','EMP_PKG','SCOTT') FROM DUAL;

SQL> show user
USER is "SYSTEM"
SQL>
SQL> l
  1* SELECT DBMS_METADATA.GET_DDL('PROCEDURE','P1','HR') FROM DUAL
SQL> /

DBMS_METADATA.GET_DDL('PROCEDURE','P1','HR')
-----------------------------------------------------------------------------

  CREATE OR REPLACE PROCEDURE "HR"."P1" ( p_id int) as
begin
   dbms_output.put

SQL>
Sendi_t
  • 617
  • 5
  • 13
  • Thank you very much for your answer. In this case, SCOTT is for my Oracle user, right? If such is the case, that doesn't work for me :( but thank you for your help. It throws me the error: 'no se ha encontrado el objeto "BVGKFDCS" del tipo PACKAGE en el esquema "SATURN"'. Where BVGKFDCS is the package and SATURN is my ORACLE user. – akolmogorov May 06 '15 at 22:25
  • Not sure why it did not work for you.. I have added **example** they way we expect it to work [see this](https://asktom.oracle.com/pls/asktom/f?p=100:11:0::::P11_QUESTION_ID:30802454515375) --- may be the user trying to query the text has correct access to do so ? – Sendi_t May 15 '15 at 16:57