Create Oracle procedure error - declare custom type - oracle

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.

Related

sql developer, function and procedures gets out of compiling

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

SQL statement ignored and missing opening parenthesis

I get these errors during a creation of a trigger but I don't understand why
create or replace NONEDITIONABLE TRIGGER magazzino_bef_ins
BEFORE INSERT ON MAGAZZINO
FOR EACH ROW
DECLARE
tempcodice varchar2(8);
cacc char(3);
ogg int;
CURSOR cursore_disp IS
SELECT cacciatore, oggetto
FROM TABLE EDDY.disponibilita
WHERE ID_DISPONIBILITA = :NEW.disponibilità;
BEGIN
CURSOR cursore_disp IS
SELECT cacciatore, oggetto
FROM TABLE DISPONIBILITA
WHERE ID_DISPONIBILITA = :NEW.disponibilità;
open cursore_disp;
fetch cursore_disp into cacc,ogg;
temp:= pk_gestione_magazzino.genera_catalogo(cacc,ogg);
:new.codcatalogo:=temp;
END;
The errors are:
Error(5,9): PL/SQL: SQL Statement ignored
Errore(6,20): PL/SQL: ORA-00906: missing opening parenthesis
Errore(9,8): PLS-00103: encountered symbol "CURSORE_DISP" instead of one of the following: := . ( # % ;
I can't understand these errors, I'm just trying to take the values from a table in where the id inserted is equal in the other table.
Here's how. I created test environment which is kind of stupid, but it makes the following code work.
SQL> create table magazzino (disponibilita number, codcatalogo varchar2(8));
Table created.
SQL> create table disponibilita (cacciatore char(3), oggetto number, id_disponibilita number);
Table created.
SQL> create or replace package pk_gestione_magazzino as
2 function genera_catalogo (cacc number, ogg number) return varchar2;
3 end;
4 /
Package created.
SQL> create or replace package body pk_Gestione_magazzino as
2 function genera_catalogo (cacc number, ogg number) return varchar2 is
3 begin
4 return 'Little';
5 end;
6 end;
7 /
Package body created.
Trigger which causes you trouble: no need for a cursor; moreover, you have two of them (was it just a typo)? It looks as if you used it to avoid no data found error. If so, don't do it - it just makes confusion. Handle exceptions properly. By the way, you "forgot" to close the cursor.
SQL> create or replace trigger magazzino_bef_ins
2 before insert on magazzino
3 for each row
4 declare
5 cacc char(3);
6 ogg int;
7 begin
8 select cacciatore, oggetto
9 into cacc, ogg
10 from disponibilita
11 where id_disponibilita = :new.disponibilita;
12
13 :new.codcatalogo := pk_gestione_magazzino.genera_catalogo (cacc, ogg);
14 end;
15 /
Trigger created.
Testing:
SQL> insert into disponibilita values (1, 1, 1);
1 row created.
SQL> insert into magazzino (disponibilita) values (1);
1 row created.
SQL> select * From magazzino;
DISPONIBILITA CODCATAL
------------- --------
1 Little
SQL>
Works, kind of.

plsql procedures while executing an error invalid identifier 00904

Error message
CREATE TABLE DEPARTMENT(DID INT,DNAME VARCHAR2(20),DLOC VARCHAR2(20));
INSERT INTO DEPARTMENT VALUES(101,'SRINATH','HINDUPUR');
INSERT INTO DEPARTMENT VALUES(102,'SAINATH','ANANTAPUR');
create or replace PROCEDURE ADD_DEPARTMENT
(P_DID IN DEPARTMENT.DID%TYPE,
P_DNAME IN DEPARTMENT.DNAME%TYPE,
P_DLOC IN DEPARTMENT.DLOC%TYPE,
P_ERROR_MSG OUT VARCHAR2)
IS
BEGIN
INSERT INTO DEPARTMENT(DID,DNAME,DLOC)VALUES(P_DID,P_DNAME,P_DLOC);
COMMIT;
EXCEPTION
WHEN OTHERS THEN
P_ERROR_MSG:=SQLERRM;
END ADD_DEPARTMENT;
iam writing a simple procedure try to excute but it shows object_id:invalid identifier how i can solve
complete procedure execution image
One of your column names may be wrong in the parameter list/insert. Try just using varchar2 for all of them and see if that helps
create or replace PROCEDURE ADD_DEPT2
(P_DEPTNO IN VARCHAR2,
P_DNAME IN VARCHAR2,
P_LOC IN VARCHAR2,
P_ERROR_MSG OUT VARCHAR2)
IS
BEGIN
INSERT INTO DEPT1(DEPTNO,DNAME,LOC)VALUES(P_DEPTNO,P_DNAME,P_LOC);
COMMIT;
EXCEPTION
WHEN OTHERS THEN
P_ERROR_MSG :=SQLERRM;
END ADD_DEPT2;
"it will come same error can be displayed"
No, no it won't. Let's prove it by running the code you posted.
Here is your table:
SQL> CREATE TABLE DEPARTMENT(DID INT,DNAME VARCHAR2(20),DLOC VARCHAR2(20));
Table created.
SQL> INSERT INTO DEPARTMENT VALUES(101,'SRINATH','HINDUPUR');
1 row created.
SQL> INSERT INTO DEPARTMENT VALUES(102,'SAINATH','ANANTAPUR');
1 row created.
SQL>
Here is your procedure:
SQL> create or replace PROCEDURE ADD_DEPARTMENT
2 (P_DID IN DEPARTMENT.DID%TYPE,
3 P_DNAME IN DEPARTMENT.DNAME%TYPE,
4 P_DLOC IN DEPARTMENT.DLOC%TYPE,
5 P_ERROR_MSG OUT VARCHAR2)
6 IS
7 BEGIN
8 INSERT INTO DEPARTMENT(DID,DNAME,DLOC)VALUES(P_DID,P_DNAME,P_DLOC);
9 COMMIT;
10 EXCEPTION
11 WHEN OTHERS THEN
12 P_ERROR_MSG:=SQLERRM;
13 END ADD_DEPARTMENT;
14 /
Procedure created.
SQL>
And lo! not only does it compile but it runs without error too.
SQL> set serveroutput on
SQL> declare
2 v varchar2(128);
3 begin
4 add_department(666, 'Area 51', 'Roswell', v);
5 end;
6 /
PL/SQL procedure successfully completed.
SQL> select * from department;
DID DNAME DLOC
---------- -------------------- --------------------
101 SRINATH HINDUPUR
102 SAINATH ANANTAPUR
666 Area 51 Roswell
SQL>
So once again I ask, what is the problem?
"PLS-00905: object SCOTT.ADD_DEPARTMENT is invalid"
In SQL*Plus:
Connect as SCOTT
alter procedure add_department compile;
show errors
Or apply the equivalent sequence for whatever IDE you use to write your code.

Oracle PL/SQL - Show results of declared table

I am using Toad. I have a declaration of a table in a package as follows:
TYPE MyRecordType IS RECORD
(ID MyTable.ID%TYPE
,FIELD1 MyTable.FIELD1%TYPE
,FIELD2 MyTable.FIELD2%TYPE
,FIELD3 MyTable.FIELD3%TYPE
,ANOTHERFIELD VARCHAR2(80)
);
TYPE MyTableType IS TABLE OF MyRecordType INDEX BY BINARY_INTEGER;
There is a procedure (lets say MyProcedure), that is using an object of this table type as input/output. I want to run the procedure and see the results (how the table is filled). So I am thinking I will select the results from the table:
declare
IO_table MyPackage.MyTableType;
begin
MyPackage.MyProcedure (IO_table
,parameter1
,parameter2
,parameter3);
select * from IO_table;
end;
I get the message:
Table or view does not exist (for IO_table). If I remove the select line, the procedure runs successfully, but I cannot see its results. How can I see the contents of IO_table after I call the procedure?
You cannot see the results for a PL/SQL table by using Select * from IO_table
You will need to loop through the collection in the annonymous block.
do something like, given in pseudo code below...
declare
IO_table MyPackage.MyTableType;
l_index BINARY_INTEGER;
begin
MyPackage.MyProcedure (IO_table
,parameter1
,parameter2
,parameter3);
l_index := IO_table.first;
While l_index is not null
loop
dbms_output.put_line (IO_table(l_index).id);
.
.
.
.
l_index :=IO_table.next(l_index_id);
end loop;
end;
You have to do it like this:
select * from TABLE(IO_table);
and, of course you missed the INTO or BULK COLLECT INTO clause
1) You can not use associated arrays in SELECT statement, Just nested tables or varrays declared globally.
2) You should use TABLE() expression in SELECT statement
3) You can't simply use SELECT in PL/SQL code - cursor FOR LOOP or REF CURSOR or BULK COLLECT INTO or INTO must be used.
4) The last but not least - please study the manual:
http://docs.oracle.com/cd/B28359_01/appdev.111/b28371/adobjcol.htm#ADOBJ00204
Just an example:
SQL> create type t_obj as object( id int, name varchar2(10));
2 /
SQL> create type t_obj_tab as table of t_obj;
2 /
SQL> var rc refcursor
SQL> declare
2 t_var t_obj_tab := t_obj_tab();
3 begin
4 t_var.extend(2);
5 t_var(1) := t_obj(1,'A');
6 t_var(2) := t_obj(2,'B');
7 open :rc for select * from table(t_var);
8 end;
9 /
SQL> print rc
ID NAME
---------- ----------
1 A
2 B

Get the name of the calling procedure or function in Oracle PL/SQL

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;

Resources