i need some help about plsql functions in stored procedure - oracle

this is my code for procedure. i have created two tables as Stud_Marks and Result with some data in it...and then i have created this procedure. at run time it shows error for "object SYS.FIND_CLASS is invalid".
SQL> create or replace procedure find_class(roll IN number) IS
2 tm number (10);
3 begin
4 select total_marks into tm from stud_marks where name IN(select name from result where roll=roll_no);
5 if(tm<=1500 and tm>=990)then
6 update result set class='distin' where roll_no=roll;
7 elseif(tm>900 and tm<989)then
8 update result set class='first' where roll_no=roll;
9 elseif(tm<=899 and tm>=825)then
10 update result set class='second' where roll_no=roll;
11 end if;
12 exception when no_data_found then
13 dbms_output.put_line('roll no is not matched with the entry');
14 end;
15 /
[enter image description here][1]
Warning: Procedure created with compilation errors
.
SQL> declare
2 r number(10);
3 begin
4 r:=&roll_no;
5 find_class(r);
6 end;
7 /
Enter value for roll_no: 1
old 4: r:=&roll_no;
new 4: r:=1;
find_class(r);
*
ERROR at line 5:
ORA-06550: line 5, column 1:
PLS-00905: object SYS.FIND_CLASS is invalid
ORA-06550: line 5, column 1:
PL/SQL: Statement ignored
then i am getting an error for find_class(r)..why???

Before calling the procedure, you must make sure it is valid. Yours isn't so Oracle raises an error.
Once you created it, you got a message saying
Warning: Procedure created with compilation errors
You should have checked what's wrong by running command
show err
I reformatted code you posted - see how it is easier to read:
create or replace procedure find_class(roll IN number) IS
tm number (10);
begin
select total_marks
into tm
from stud_marks
where name IN (select name
from result
where roll = roll_no
);
if (tm <= 1500 and tm >= 990)then
update result set
class = 'distin'
where roll_no = roll;
elsif (tm > 900 and tm < 989) then --> ELSIF, not ELSEIF
update result set
class = 'first'
where roll_no = roll;
elsif (tm <= 899 and tm >= 825) then --> ELSIF, not ELSEIF
update result set
class = 'second'
where roll_no = roll;
end if;
exception when no_data_found then
dbms_output.put_line('roll no is not matched with the entry');
end;
Apparently, you used ELSEIF while it should be ELSIF. I don't know whether that's the only error as I don't have your tables - you'll find that out. Don't forget to show err if necessary!
So, once it is created without errors, you can call it and see what it does.
P.S. Forgot to mention: why do you do it connected as SYS? That user owns the database and should not be used for development or educational purposes. You should use one of predefined users (such as Scott or HR) or create your own user. Leave SYS alone.

Related

PLS-00103: Encountered the symbol " " when expecting one of the following: := . ( # % ; not null range default character

Why doesn't this work?
Any advice or solutions are greatly appreciated.
CREATE OR REPLACE TRIGGER OverReading
BEFORE UPDATE OR INSERT ON MeterReadings
FOR EACH ROW
DECLARE
emp_counter INTEGER;
max_meter INTEGER : = 5;
BEGIN
SELECT COUNT(EmployeeId) INTO emp_counter
FROM MeterReadings
WHERE EmployeeId = :NEW.EmployeeId;
IF : OLD.EmployeeId = NEW.EmployeeId THEN
RETURN;
ELSIF emp_counter >= max_meter THEN
raise_application_error(-20900,'Employee are limited to a maximum of 5 meters');
END IF;
END;
/
The Error that is thrown to me
Three syntax errors, all of them related to : character.
When fixed, trigger compiles:
SQL> CREATE OR REPLACE TRIGGER OverReading
2 BEFORE UPDATE OR INSERT ON MeterReadings
3 FOR EACH ROW
4 DECLARE
5 emp_counter INTEGER;
6 max_meter INTEGER := 5; --> here
7 BEGIN
8 SELECT COUNT(EmployeeId) INTO emp_counter
9 FROM MeterReadings
10 WHERE EmployeeId = :NEW.EmployeeId;
11 IF :OLD.EmployeeId = :NEW.EmployeeId THEN --> 2x here
12 RETURN;
13 ELSIF emp_counter >= max_meter THEN
14 raise_application_error(-20900,'Employee are limited to a maximum of 5 meters');
15 END IF;
16 END;
17 /
Trigger created.
SQL>
However: this code will run if you insert rows one-by-one. Otherwise, it will raise mutating table error as you're selecting from the same table you're inserting into (which is not allowed). If that bothers you, there are ways to fix it. Depending on database version you use, it could be a compound trigger or a type + package option.

Stored procedure ERROR 1520: File No:ORA-06502: PL/SQL: numeric or value error when calling it from oracle_cx python driver

I am calling a stored procedure from Python program.
There is an issue that happens on certain values.
For example it fails when i send values 2020,2017 but it succeeds wen I send 2010,2050 etc. What can be the issue?
DB Version: NLSRTL Version 11.2.0.4.0 - Production
Oracle_cx: latest
Procedure parameter that causes the issue : P_FILE_YEAR IN NUMBER
Error Message: ERROR 1520: File No:ORA-06502: PL/SQL: numeric or value error: number precision too large
It fails in the following exception:
BEGIN
SELECT MAX(mlal_file_no) + 1
INTO ln_file_no
FROM doc_mail_allocation
WHERE mlal_file_year = P_FILE_YEAR
AND std_file_type_code = 2 ;
EXCEPTION
WHEN no_data_found THEN
ln_file_no := 1 ;
WHEN OTHERS THEN
p_error_code := 1 ;
p_error_msg := 'ERROR 1520: File No:'||SQLERRM||' AND flal_file_year = '||P_FILE_YEAR;
RETURN ;
END ;
Looks like this:
Sample data:
SQL> select * From doc_mail_allocation;
MLAL_FILE_YEAR STD_FILE_TYPE_CODE MLAL_FILE_NO
-------------- ------------------ ------------
2010 2 100
2020 2 999
Your code:
SQL> declare
2 ln_file_no number(3);
3 begin
4 SELECT MAX(mlal_file_no) + 1
5 INTO ln_file_no
6 FROM doc_mail_allocation
7 WHERE mlal_file_year = &P_FILE_YEAR
8 AND std_file_type_code = 2 ;
9 dbms_output.put_line('result = ' || ln_file_no);
10 end;
11 /
Enter value for p_file_year: 2010
result = 101
PL/SQL procedure successfully completed.
SQL> /
Enter value for p_file_year: 2020
declare
*
ERROR at line 1:
ORA-06502: PL/SQL: numeric or value error: number precision too large
ORA-06512: at line 4
SQL>
See the difference & error cause? If you declared a variable as "too small" (number(3)), for year 2020 MAX(mlal_file_no) + 1 equals 1000 and it can't fit into such a variable.
Solution? Enlarge ln_file_no, or check why this happens (if it shouldn't) - then there's error in data.

PL/SQL IF statement and variable declaration

I am trying to make the code posted below work, but I am receiving an error about the IF statement:
DECLARE
a number;
BEGIN
SELECT Pers_API.Is_Manager_(10018) INTO a from dual;
EXCEPTION
WHEN no_data_found THEN a := 0;
END;
IF (a >0) THEN
SELECT 1 from dual;
ELSE
SELECT 0 from dual;
END IF;
In the first block I am declaring an 'A' variable and setting it to 0 (by the way, the API call result will be 0 or 1, nothing else). The first block works fine or - at least - I do think so. But the IF block is not working and having this error:
PLS-00103:Encountered the symbol "IF"
Any help is appreciated.
Update: I have tried it this way:
DECLARE
a number:=0;
BEGIN
SELECT Pers_API.Is_Manager_(10018) INTO a from dual;
IF (:a >0) THEN
SELECT 1 from dual;
ELSE
SELECT 0 from dual;
END IF;
END;
I received the exception below:
ORA-01008: not all variables bound
Update
In other words, what I am trying to do is:
if Pers_API.Is_Manager_(10018) returns true (as 1), I have to do another select statement
if it's false (as 0), I have to return null.
Any other ideas are appreciated.
A few objections, if I may.
there's no need to select from dual in order to assign a value to a variable, when that value is returned by a function - simply assign it
exception handler seems to be superfluous. You said that the is_manager_ function returns 0 or 1 and nothing else. Therefore, it'll always return something, so - why do you expect that SELECT to return NO_DATA_FOUND? Besides, such a case should be handled by the function itself (i.e. you have to make sure that it returns 0 or 1 and nothing else)
the last paragraph you wrote is somewhat strange. You said that - if the function returns 1, you have to run another SELECT statement. Otherwise, you have to return null (while code you wrote, select 0 ... suggests a zero (0), not null); so, which one is true?
also, saying that you have to return something (null, 0, whatever) suggests that piece of code you wrote should be a function that returns a value. Is that so?
Code that actually compiles might look like in this example.
First, a function (based on Scott's schema) that checks whether an employee is a manager:
SQL> create or replace function is_manager_ (par_empno in number)
2 return number
3 is
4 /* function checks whether PAR_EMPNO belongs to a manager and returns:
5 - 1 - employee is a manager
6 - 0 - employee is NOT a manager
7 */
8 retval number := 0;
9 begin
10 select max(1)
11 into retval
12 from emp e
13 where mgr = par_empno;
14
15 return retval;
16 exception
17 when no_data_found then
18 return retval;
19 end;
20 /
Function created.
SQL>
Code you posted, rewritten so that it does something:
if an employee is a manager, returns his/her salary
otherwise, it does not
SQL> declare
2 a number := is_manager_(&&l_empno);
3 l_sal emp.sal%type;
4 begin
5 if a > 0 then
6 select sal
7 into l_sal
8 from emp
9 where empno = &&l_empno;
10 dbms_output.put_line('Employee is a manager and his/her salary is ' || l_sal);
11 else
12 null;
13 dbms_output.put_line('Employee is not a manager');
14 end if;
15 end;
16 /
Enter value for l_empno: 7698
Employee is a manager and his/her salary is 2850
PL/SQL procedure successfully completed.
SQL> undefine l_empno
SQL> /
Enter value for l_empno: 7369
Employee is not a manager
PL/SQL procedure successfully completed.
SQL> undefine l_empno
SQL> /
Enter value for l_empno: -1
Employee is not a manager
PL/SQL procedure successfully completed.
SQL>
See if you can adjust it so that it fits your needs. If not, do answer to my objections posted at the beginning of this message, and we'll see what to do next.
It appears to me that what you are really trying to achieve here is to run a query which must use the result obtained from the package function as a condition. If so, the PL/SQL block wouldn't be needed and can be written as a basic select operation.
What is still not clear from your explanation is whether your select query
SELECT 1 from dual is the actual query you are about to use in your code.Generally, in the select statement, we use CASE expression to evaluate the conditional logic, which essentially does what IF ELSE condition was supposed to do to return the desired result.The query would have a structure of this form,
SELECT
CASE
WHEN pers_api.is_manager_(10018) = 1 THEN some_expression
ELSE some_other_expression --If you omit the else condition, it defaults to null when all others are false
END
END
as
FROM DUAL;
More specifically, if you want to have the resultant expression come from another database table, the queries can take the form
SELECT
CASE
WHEN pers_api.is_manager_(10018) = 1 THEN some_expression
ELSE some_other_expression --If you omit the else condition, it defaults to null when all others are false
END
as
FROM table_to_run_query
WHERE where_clauses = some_values;
If you say that your resultant expression from the table involves many other constructs, the challenge would be to compose it in a single query cleverly to avoid any PL/SQL at all. That would be achievable, but it will require that you explain us with some sample data and expected result, as to what exactly you want,preferably in a new question.
It would not be complete if I don't mention the REFCURSOR technique to obtain results from a select query in PL/SQL. It is either through DBMS_SQL.RETURN_RESULT(Oracle 12c and above) or using a REFCURSOR bind variable running it in SQL* Plus or as Script in other tools (F5).
VARIABLE x refcursor;
DECLARE BEGIN
IF
pers_api.is_manager_(10018) = 1
THEN
OPEN :x FOR SELECT some_columns FROM some_tables;
ELSE
OPEN :x FOR SELECT some_columns FROM other_tables;
END IF;
--DBMS_SQL.RETURN_RESULT(:x); --12c and above
END;
/
PRINT x -- 11g

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;

Oracle SQL Trigger for set min Value to INT Field on NULL

I am trying to get a trigger on the table PACKS that set a min Value in INT Field - PRICE when inserting a new PACK - for example '333'. for insert calling a Procedure new pack.
thats the trigger:
CREATE OR REPLACE TRIGGER pack_min_price
BEFORE
INSERT
ON PACKS
FOR EACH ROW
BEGIN
IF new.PRICE < 333 THEN
:new.PRICE := :new.PRICE + 333;
END IF;
END;
and thats the PROCEDURE:
create or replace PROCEDURE newPack(
cntr IN PACKS.COUNTRY%TYPE,
trns IN PACKS.TRANSPORT%TYPE,
htl IN PACKS.HOTEL%TYPE,
extr IN PACKS.HOTELEXTRAS%TYPE,
othextr IN PACKS.OTHEREXTRAS%TYPE,
strdt IN PACKS.STARTDATE%TYPE,
enddt IN PACKS.ENDDATE%TYPE,
prc IN PACKS.PRICE%TYPE)
IS
BEGIN
INSERT INTO PACKS
(COUNTRY,TRANSPORT,HOTEL,HOTELEXTRAS,OTHEREXTRAS,STARTDATE,ENDDATE,PRICE)
VALUES
(cntr,trns,htl,extr,othextr,strdt,enddt,prc);
COMMIT;
END;
the error i get when i try to compile the trigger -
Compilation failed, line 2 (10:12:41) The line numbers associated with compilation errors are relative to the first BEGIN statement. This only affects the compilation of database triggers.
PLS-00201: identifier 'NEW.PRICE' must be declaredCompilation failed, line 2 (10:12:41) The line numbers associated with compilation errors are relative to the first BEGIN statement. This only affects the compilation of database triggers.
PL/SQL: Statement ignored
and when i start the procedure -
ORA-04098: trigger 'PROJECT160.PACK_MIN_PRICE' is invalid and failed re-validation
without the Trigger the Procedure is working perfectly fine. Can you help? thx
You are missing the : on the new instance in the IF statement.
IF :new.PRICE < 333 THEN
:new.PRICE := :new.PRICE + 333;
END IF;

Resources