sql developer, function and procedures gets out of compiling - oracle

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

Related

how to increase column length without making dependent types invalid in oracle

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

PL/SQL Stored Procedure - return records from a table

I am very new to doing SQL work. I was wondering how I return a select statement in a stored procedure in PL/SQL.
My understanding so far (that is little) is that I should put the return of the data in a table and assign the data within the table to a reference cursor. With that loaded then LOOP through the REF Cursor and present the data back?
Actually converting that into code for a stored procedure has lost me completely with little examples to see with my use case. Any help is appreciated.
Many thanks in advance :)
Here's one example: procedure has only one - OUT - parameter, which is a refcursor:
SQL> create or replace procedure p_test (par_rc out sys_refcursor)
2 is
3 begin
4 open par_rc for select deptno, dname, loc from dept;
5 end;
6 /
Procedure created.
In order to call such a procedure, you need to store the result into something. In order to do that, I'll declare a variable (in SQL*Plus, which is a tool I use for this example) and call the procedure using begin-end block, providing the variable name as its parameter:
SQL> var l_rc refcursor;
SQL>
SQL> begin
2 p_test (:l_rc);
3 end;
4 /
PL/SQL procedure successfully completed.
Print the result:
SQL> print l_rc
DEPTNO DNAME LOC
---------- -------------- -------------
10 ACCOUNTING NEW YORK
20 RESEARCH DALLAS
30 SALES CHICAGO
40 OPERATIONS BOSTON
SQL>
There might be other options, which depend on what you really are doing.
Usually a stored procedure is used to perform manipulations of data in the database, and functions are used to return values or data. If you're just trying to use a select statement within a stored procedure, then you would want to use a cursor, which is something you declare like any other variable at the beginning of the procedure, and then open either implicitly or explicitly within the procedure code.
Example of an implicit cursor:
declare
cursor sample_cur is --this can be your select statement
select sysdate as today from dual;
begin
for rec in sample_cur loop
-- step by step for each record you return in your cursor
dbms_output.put_line(rec.today);
end loop;
end;

Function created with compilation error in PLSQL

When I compile the below code I am getting a error message "Function created with compilation errors"
create or replace function find_port(ip_ID in int) RETURN int
is
t_count number;
count varchar;
begin
select is_rail into count from table where id = ip_ID;
case
when count ='True' then t_count:=1;
when count ='False' then t_count:=0;
end case;
end;
/
i am getting a error message "Function created with compilation errors"
So the question you should be asking is, "how do I get a list of compilation errors for my PL/SQL code?"
Other people have told you how to fix the current errors in your code, but the more important skill is that you find out how to diagnose your code for yourself.
Oracle is a database, and it stores metadata in a set of special views called the data dictionary. These views include views for compilation errors. This query will work in any SQL environments:
select name, type, line, text -- or just *, obvs
from user_errors ue
order by ue.name, ue.type, ue.sequence;
There are also ALL_ERRORS and DBA_ERRORS views. Find out more.
In SQL*Plus you can run sho err (short for show errors). IDEs like PL/SQL Developer or Oracle SQL Developer will show compilation errors automatically.
Once you know how to get the text of the errors you need to know that LINE will tell you the line where the error is raised. Although with certain classes of error (such as missing commas or unmatched brackets) the indicated line may not be the line where the actual error resides. Unfortunately there is still a need for interpretation and understanding, which requires experience.
Actually, COUNT can be used as a PL/SQL variable:
SQL> create or replace function f_test return int is
2 count number;
3 begin
4 select 1 into count from dual;
5 return 2;
6 end;
7 /
Function created.
SQL> select f_test from dual;
F_TEST
----------
2
SQL>
However, you can't return it:
SQL> create or replace function f_test return int is
2 count number;
3 begin
4 select 1 into count from dual;
5 return count;
6 end;
7 /
Warning: Function created with compilation errors.
SQL> show err
Errors for FUNCTION F_TEST:
LINE/COL ERROR
-------- -----------------------------------------------------------------
5/3 PL/SQL: Statement ignored
5/10 PLS-00204: function or pseudo-column 'COUNT' may be used inside a
SQL statement only
SQL>
Here, #priya, you can see how to help yourself - SHOW ERR will tell you what's wrong with your code.
Apart from that, CASE statement you used was invalidly written; should have been similar to this:
SQL> create or replace function f_test return int is
2 l_count number;
3 t_count number;
4 begin
5 select 1 into l_count from dual;
6
7 t_count := case when l_count = 1 then 1
8 when l_count = 2 then 2
9 end;
10
11 return t_count;
12 end;
13 /
Function created.
SQL> select f_test from dual;
F_TEST
----------
1
SQL>
count is a SQL function and thus not a better choice to be used as a PL/SQL variable. The CASE block can be used within the select statement.
Furthermore, your function does not RETURN any value.
create or replace function find_port(ip_ID in int) RETURN int
is
t_count number;
begin
select case
when is_rail = 'True' then 1
when is_rail = 'False' then 0
end into t_count from yourtable where id=ip_ID;
RETURN t_count;
end;

ALL_PROCEDURES view doesn't show the PROCEDURE_NAME

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.

Create Oracle procedure error - declare custom type

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.

Resources