Why can't I see my procedure in user_procedures view? Why is the procedure_name filter on all_procedures view returns no rows.
This question is primarily to aid those who are searching for a similar question. I hope that anyone looking for such question would find a answer here.
Test case :
SQL> show user
USER is "LALIT"
SQL> CREATE OR REPLACE
2 PROCEDURE new_proc
3 AS
4 BEGIN
5 NULL;
6 END;
7 /
Procedure created.
SQL>
SQL> SELECT owner,
2 object_name,
3 procedure_name,
4 object_type
5 FROM all_procedures
6 WHERE owner='LALIT'
7 AND procedure_name='NEW_PROC';
no rows selected
SQL>
From documentation,
ALL_PROCEDURES lists all functions and procedures, along with
associated properties. For example, ALL_PROCEDURES indicates whether
or not a function is pipelined, parallel enabled or an aggregate
function. If a function is pipelined or an aggregate function, the
associated implementation type (if any) is also identified.
It doesn't clarify whether it would list a STAND ALONE PROCEDURE and a procedure wrapped in a PACKAGE the same way or does it consider it differently. Since, the procedure_name would not list the name of a stand alone procedure as seen in the test case in the question above.
PROCEDURE_NAME column will only have the procedure name for the procedures which are part of a PACKAGE. For STAND ALONE PROCEDURES you need to use OBJECT_NAME.
SQL> show user
USER is "LALIT"
SQL> CREATE OR REPLACE
2 PROCEDURE new_proc
3 AS
4 BEGIN
5 NULL;
6 END;
7 /
Procedure created.
SQL>
SQL> SELECT owner,
2 object_name,
3 procedure_name,
4 object_type
5 FROM all_procedures
6 WHERE owner='LALIT'
7 AND object_name='NEW_PROC';
OWNER OBJECT_NAME PROCEDURE_NAME OBJECT_TYPE
----- --------------- --------------- ---------------
LALIT NEW_PROC PROCEDURE
SQL>
You could get the list of procedures using procedure_name only if it is wrapped in a package.
SQL> -- package
SQL> CREATE OR REPLACE
2 PACKAGE new_pack
3 IS
4 PROCEDURE new_proc;
5 END new_pack;
6 /
Package created.
SQL>
SQL> -- package body with a procedure
SQL> CREATE OR REPLACE
2 PACKAGE BODY new_pack
3 IS
4 PROCEDURE new_proc
5 IS
6 BEGIN
7 NULL;
8 END;
9 END new_pack;
10 /
Package body created.
SQL> SELECT owner,
2 object_name,
3 procedure_name,
4 object_type
5 FROM all_procedures
6 WHERE owner='LALIT'
7 AND procedure_name='NEW_PROC';
OWNER OBJECT_NAME PROCEDURE_NAME OBJECT_TYPE
----- --------------- --------------- -----------
LALIT NEW_PACK NEW_PROC PACKAGE
SQL>
Now you could see the procedure_name as the actual procedure, and the object_name as the package_name.
Of course, mostly in production systems we would have packages, and not stand alone procedures. But, while testing and demos, we do compile and run stand alone procedures. So, it is good to know how Oracle maintains the information in *_PROCEDURES views.
Related
I work in a company where there are many processes that are executed on an ORACLE server, with lots of functions and procedures that are constantly running different data (all types of data)
Yesterday, we noticed a slowdown in the system, and even a partial halt in traffic on the DB side. After testing our DBA man using SQL DEVELOPER, he founds about 15 functions and procedures that came out of compilation.
That is, no changes were made to them, but the icons of all of those 15 functions/procedures showed that they were not compiled, it was necessary to click on 'Recompile' to use them again, thus restoring the system to normal operation.
Up to this moment, we do not know how to explain what caused 15 functions and a procedure to go out of compilation at the same time, but certainly no employee has touched on these functions / procedures. First time such a thing happens to us, and we have not heard of a similar case.
Does anyone have any idea what could have made this happen? Maybe a problematic type of information got into DB that caused a problematic chain reaction?
Maybe some other object - that is used by all those functions and procedures - was modified (e.g. package specification), and it "invalidated" all objects that reference it.
Basically, you don't have to do anything - Oracle will automatically recompile them as soon as someone calls them.
Here's an example.
Package with a single function:
SQL> create or replace package pkg_test as
2 function f_test (par_number in number) return number;
3 end;
4 /
Package created.
SQL> create or replace package body pkg_test as
2 function f_test (par_number in number) return number
3 is
4 begin
5 return par_number;
6 end;
7 end;
8 /
Package body created.
Standalone function that references (calls) function from the package;
SQL> create or replace function f_test_2 (par_number in number)
2 return number
3 is
4 begin
5 return pkg_test.f_test(par_number);
6 end;
7 /
Function created.
What is its status? It is VALID:
SQL> select object_name, object_type, status from user_objects where object_name = 'F_TEST_2';
OBJECT_NAME OBJECT_TYPE STATUS
-------------------- ------------------- -------
F_TEST_2 FUNCTION VALID
Does it work? YES:
SQL> select f_test_2 (100) result from dual;
RESULT
----------
100
SQL>
OK, let's now slightly modify the packaged function's spec (I'll add the DEFAULT clause):
SQL> create or replace package pkg_test as
2 function f_test (par_number in number default 0) return number;
3 end;
4 /
Package created.
SQL> create or replace package body pkg_test as
2 function f_test (par_number in number default 0) return number
3 is
4 begin
5 return par_number;
6 end;
7 end;
8 /
Package body created.
I didn't modify standalone function f_test_2. What is its status? It is now INVALID:
SQL> select object_name, object_type, status from user_objects where object_name = 'F_TEST_2';
OBJECT_NAME OBJECT_TYPE STATUS
-------------------- ------------------- -------
F_TEST_2 FUNCTION INVALID --> see? INVALID
Can I use it (without recompiling it)? Yes, I can:
SQL> select f_test_2 (500) result from dual;
RESULT
----------
500
SQL>
Usually this occurs when someone changes a dependency (for example: TYPE, TABLE, FUNCTION, PROCEDURE, PACKAGE, etc.) of the function/procedure.
For example:
CREATE TYPE obj IS OBJECT (a INT, b INT);
CREATE PROCEDURE proc(v_obj IN obj)
IS BEGIN NULL; END;
/
Then both are valid. If you then do:
CREATE OR REPLACE TYPE obj IS OBJECT (a NUMBER(5,0), b NUMBER(5,0));
Then SELECT object_name, object_type, status FROM USER_OBJECTS; outputs:
OBJECT_NAME
OBJECT_TYPE
STATUS
OBJ
TYPE
VALID
PROC
PROCEDURE
INVALID
If you then do:
ALTER PROCEDURE proc COMPILE;
Then the procedure is valid again.
db<>fiddle here
I have gone through similar threads but unable to understand the root cause of the error.
I have an Oracle Schema as "PRP".
PRP has one table Named : "MY_TABLE".
PRP has one package Named : "My_PKG" with authid current_user
Package contains following procedure
PROCEDURE CUSTOMER_ORDER_QUERY (
P_REPORT OUT SYS_REFCURSOR
) AS
BEGIN
OPEN P_REPORT FOR SELECT
* from MY_TABLE
END;
When I execute the procedure from the package it gives the error Table or view does not exists.
But when I prefix the schema name to the table in the procedures the cursor executes perfectly.
I have explicitly given privileges on that table to same schema.
from sys users : grant all on prp.MY_TABLE to PRP;
But none helps.
The Package and the table is in same schema.
Please help.
I did what you described; no problems.
Create user prp and grant required privileges:
SQL> connect sys as sysdba
Enter password:
Connected.
SQL> create user prp identified by prp
2 default tablespace users
3 temporary tablespace temp
4 quota unlimited on users;
User created.
SQL> grant create session, create table, create procedure to prp;
Grant succeeded.
Connect as prp, create table and package:
SQL> connect prp/prp
Connected.
SQL> create table my_table as
2 select 1 id, 'Little' name from dual union all
3 select 2 , 'Foot' from dual;
Table created.
SQL> create or replace package my_pkg as
2 procedure customer_order_query (p_report out sys_refcursor);
3 end;
4 /
Package created.
SQL> create or replace package body my_pkg as
2 procedure customer_order_query (p_report out sys_refcursor)
3 as
4 begin
5 open p_report for select * from my_table;
6 end;
7 end;
8 /
Package body created.
Testing:
SQL> var l_rc refcursor
SQL> exec my_pkg.customer_order_query (:l_rc);
PL/SQL procedure successfully completed.
SQL> print l_rc;
ID NAME
---------- ------
1 Little
2 Foot
SQL>
So, yes - it works. If both table and package belong to the same user (reside in the same schema), you don't need any additional privileges as you own both of them.
I need to increase a column length in oracle table. But there is type defined on same table inside a package specification. This package is being used in more than 1000 packages.
So when I alter column, all packages become invalid.
Is there a way, so I can increase column length without making dependent type invalid.
Thanks.
You don't need to do anything; Oracle will recompile (or, at least try to do so) those packages and make them VALID (unless something else prevents that).
Here's a simple demonstration.
Test case first:
SQL> create table test (name varchar2(5));
Table created.
SQL> insert into test
2 select 'Littl' from dual union all
3 select 'Foot' from dual;
2 rows created.
SQL> create or replace package pkg_test as
2 function f_test return test.name%type;
3 end;
4 /
Package created.
SQL> create or replace package body pkg_test as
2 function f_test return test.name%type is
3 retval test.name%type;
4 begin
5 select max(name) into retval from test;
6 return retval;
7 end;
8 end;
9 /
Package body created.
SQL>
Let's check package's status and see function's result:
SQL> select object_name, status From user_objects where object_name = 'PKG_TEST';
OBJECT_NAM STATUS
---------- -------
PKG_TEST VALID
PKG_TEST VALID
SQL> select pkg_test.f_test from dual;
F_TEST
--------------------------------------------------------------------------------
Littl
SQL>
Everything is OK.
Now, enlarge the column and see what happens:
SQL> alter table test modify name varchar2(10);
Table altered.
SQL> select object_name, status From user_objects where object_name = 'PKG_TEST';
OBJECT_NAM STATUS
---------- -------
PKG_TEST INVALID
PKG_TEST INVALID
SQL> select pkg_test.f_test from dual;
F_TEST
--------------------------------------------------------------------------------
Littl
SQL> select object_name, status From user_objects where object_name = 'PKG_TEST';
OBJECT_NAM STATUS
---------- -------
PKG_TEST VALID
PKG_TEST VALID
SQL>
See? It just works. Package was initially INVALID, was recompiled in the background and became VALID.
So, no worries. I'd just say congratulations you decided to declare everything so that it inherits column's datatype. If you hardcoded it, then you'd have a BIG problem in manually modifying all those variables, whatnot, to make everything work.
You can check online table redefinition in which case only affected column's dependent objects will become invalid. For example if the column you are altering is not dependant on the type in the same table declared in packages then those packages will remain valid.Even for normal alter command this condition applies but online redefinition allows using a interim table to support dml operations during the alterations
Anyway since it is a production system I suggest testing this feature in UAT and then work it out in production
Does anyone know whether it's possible for a PL/SQL procedure (an error-logging one in this case) to get the name of the function/procedure which called it?
Obviously I could pass the name in as a parameter, but it'd be nice to make a system call or something to get the info - it could just return null or something if it wasn't called from a procedure/function.
If there's no method for this that's fine - just curious if it's possible (searches yield nothing).
There is a package called OWA_UTIL (which is not installed by default in older versions of the database). This has a method WHO_CALLED_ME() which returns the OWNER, OBJECT_NAME, LINE_NO and CALLER_TYPE. Note that if the caller is a packaged procedure it will return the PACKAGE name not the procedure name. In this case there is no way of getting the procedure name; this is because the procedure name can be overloaded, so it's not necessarily very useful.
Find out more.
Since 10gR2 there is also the $$PLSQL_UNIT special function; this will also return the OBJECT NAME (i.e. package not packaged procedure).
I found this forum: http://www.orafaq.com/forum/t/60583/0/. It may be what you are looking.
Basically, you can use the Oracle supplied dbms_utility.format_call_stack:
scott#ORA92> CREATE TABLE error_tab
2 (who_am_i VARCHAR2(61),
3 who_called_me VARCHAR2(61),
4 call_stack CLOB)
5 /
Table created.
scott#ORA92>
scott#ORA92> CREATE OR REPLACE PROCEDURE d
2 AS
3 v_num NUMBER;
4 v_owner VARCHAR2(30);
5 v_name VARCHAR2(30);
6 v_line NUMBER;
7 v_caller_t VARCHAR2(100);
8 BEGIN
9 select to_number('a') into v_num from dual; -- cause error for testing
10 EXCEPTION
11 WHEN OTHERS THEN
12 who_called_me (v_owner, v_name, v_line, v_caller_t);
13 INSERT INTO error_tab
14 VALUES (who_am_i,
15 v_owner || '.' || v_name,
16 dbms_utility.format_call_stack);
17 END d;
18 /
Procedure created.
scott#ORA92> SHOW ERRORS
No errors.
scott#ORA92> CREATE OR REPLACE PROCEDURE c
2 AS
3 BEGIN
4 d;
5 END c;
6 /
Procedure created.
scott#ORA92> CREATE OR REPLACE PROCEDURE b
2 AS
3 BEGIN
4 c;
5 END b;
6 /
Procedure created.
scott#ORA92> CREATE OR REPLACE PROCEDURE a
2 AS
3 BEGIN
4 b;
5 END a;
6 /
Procedure created.
scott#ORA92> execute a
PL/SQL procedure successfully completed.
scott#ORA92> COLUMN who_am_i FORMAT A13
scott#ORA92> COLUMN who_called_me FORMAT A13
scott#ORA92> COLUMN call_stack FORMAT A45
scott#ORA92> SELECT * FROM error_tab
2 /
WHO_AM_I WHO_CALLED_ME CALL_STACK
------------- ------------- ---------------------------------------------
SCOTT.D SCOTT.C ----- PL/SQL Call Stack -----
object line object
handle number name
6623F488 1 anonymous block
66292138 13 procedure SCOTT.D
66299430 4 procedure SCOTT.C
6623D2F8 4 procedure SCOTT.B
6624F994 4 procedure SCOTT.A
66299984 1 anonymous block
scott#ORA92>
Basically, all you need to do is to define vars and pass them in a call to a utility method to fill them up with values:
create or replace procedure some_test_proc (p_some_int int)
is
owner_name VARCHAR2 (100);
caller_name VARCHAR2 (100);
line_number NUMBER;
caller_type VARCHAR2 (100);
begin
....
OWA_UTIL.WHO_CALLED_ME (owner_name,caller_name,line_number,caller_type);
-- now you can insert those values along with systimestamp into a log file
....
end;
I'm attempting to create a procedure in Oracle Express Server (Application Express 2.1.0.00.39) using the web interface.
This is the SQL I'm running via the SQL Commands option in the web interface
CREATE OR REPLACE PROCEDURE my_procedure (listOfNumbers num_list,
v_value varchar2)
IS
PRAGMA AUTONOMOUS_TRANSACTION;
BEGIN
UPDATE my_table
SET my_column = v_value
WHERE my_row_id IN (SELECT column_value
FROM TABLE(listOfNumbers));
COMMIT;
END;
UPDATE:
Changed SELECT column_value FROM TABLE to SELECT column_value FROM TABLE(listOfNumbers) but now I get the following error:
PLS-00201: identifier 'num_list' must
be declared
UPDATE 2:
Here is how I created my type:
CREATE OR REPLACE TYPE "num_list" as table of NUMBER(38,1)
/
Seems the error is being caused on the parameter declaration line:
(listOfNumbers num_list, v_value varchar2)
Below is the object details as displayed by the Oracle Database Express Edition web interface.
Try ...TABLE(CAST(listOfNumbers AS num_list)).
The SQL parser simply sees a bind placeholder in place of listOfNumbers, and since it's a custom type you need to tell it what type it is.
This will only work if num_list has been defined as a type in the schema, not just declared as a type in a PL/SQL block.
Your code works - providing the array type has been declared correctly (see below). As you are still having a problem I suspect that is where you are going wrong. But you need to post the code you are using to create the NUM_LIST type in order for us to correct it.
My test data:
SQL> select * from my_table
2 /
MY_COLUMN MY_ROW_ID
-------------------- ----------
APC 1
XYZ 2
JFK 3
SQL>
In order to use a type in a SQL statement we must create it as a SQL object:
SQL> create type num_list as table of number;
2 /
Type created.
SQL>
SQL>
SQL> create or replace procedure my_procedure
2 (listofnumbers num_list,
3 v_value varchar2)
4 is
5 begin
6
7 update my_table
8 set my_column = v_value
9 where my_row_id in (select column_value
10 from table(listofnumbers));
11
12 end;
13 /
Procedure created.
SQL>
Executing the procedure:
SQL> declare
2 n num_list := num_list(1,3);
3 begin
4 my_procedure (n , 'FOX IN SOCKS');
5 end;
6 /
PL/SQL procedure successfully completed.
SQL>
And lo!
SQL> select * from my_table
2 /
MY_COLUMN MY_ROW_ID
-------------------- ----------
FOX IN SOCKS 1
XYZ 2
FOX IN SOCKS 3
SQL>
Apparently I was creating the type with quotes around the name:
The following didn't work:
CREATE OR REPLACE TYPE "NUMBER_T" as table of NUMBER(38,1)
When I did it without the quotes and then created the procedure, it was able to recognize it.
The following did work:
CREATE OR REPLACE TYPE NUMBER_T as table of NUMBER(38,1)
I'm not sure why, but it worked.