The following Oracle statement:
CREATE OR REPLACE PACKAGE BODY pk1
IS
FUNCTION RETURN_BOOLEAN(v_accno bank.accno%TYPE)
RETURN BOOLEAN
IS
BEGIN
SELECT COUNT(*) INTO v_count
FROM bank
WHERE accno = v_accno;
IF v_count = 0 THEN
RETURN TRUE;
ELSE
RETURN FALSE;
END IF;
END;
Gives me the following error:
13/4 PLS-00103: Encountered the symbol "end-of-file" when expecting one of the following: begin end function pragma procedure Errors: check compiler log
What is opened, must be closed - you didn't close package body. It is a good habit to specify which procedure you're actually closing (see all END lines).
Also, you have to declare a variable (v_count).
SQL> CREATE OR REPLACE PACKAGE pk1
2 AS
3 FUNCTION return_boolean (v_accno bank.accno%TYPE)
4 RETURN BOOLEAN;
5 END pk1;
6 /
Package created.
SQL> CREATE OR REPLACE PACKAGE BODY pk1
2 IS
3 FUNCTION return_boolean (v_accno bank.accno%TYPE)
4 RETURN BOOLEAN
5 IS
6 v_count NUMBER;
7 BEGIN
8 SELECT COUNT (*)
9 INTO v_count
10 FROM bank
11 WHERE accno = v_accno;
12
13 IF v_count = 0
14 THEN
15 RETURN TRUE;
16 ELSE
17 RETURN FALSE;
18 END IF;
19 END return_boolean;
20 END pk1;
21 /
Package body created.
SQL>
Note that you could have simplified the return statement to just one line:
RETURN v_count = 0;
(no need for IF-THEN-ELSE).
The function declaration also needs a closing END keyword. Either just END; or END <function_name>; works.
CREATE OR REPLACE PACKAGE BODY pk1
IS
FUNCTION RETURN_BOOLEAN(v_accno bank.accno%TYPE)
RETURN BOOLEAN
IS
v_count NUMBER;
BEGIN
SELECT COUNT(*) INTO v_count
FROM bank
WHERE accno = v_accno;
IF v_count = 0 THEN
RETURN TRUE;
ELSE
RETURN FALSE;
END IF;
END RETURN_BOOLEAN;
END;
ah and you missed the declaration of v_count
Related
I have written some code to print whether the condition is true/false, but I can't get the output as true / false. Why?
Here is that code:
create or replace PROCEDURE TET_STOP_DID
IS
result VARCHAR2(10);
LastGeneratedcode TET_LASTGENERATEDMASKCODE.Maskedcode%TYPE;
BEGIN
select maskedcode into LastGeneratedcode from TET_LASTGENERATEDMASKCODE;
IF (SUBSTR(LastGeneratedcode,5,5) !='ZZZZZ') then
result := 'true';
else
result :='false';
END IF;
END TET_STOP_DID;
You aren't printing anything; you've just set the result variable to some value, and that's it. Though, that procedure doesn't look right as it'll raise too_many_rows error if there are two (or more) rows in the table (or no_data_found if it is empty). I presume you'd want to pass some parameter which restricts number of fetched rows.
For example:
SQL> select * from tet_lastgeneratedmaskcode;
ID MASK
---------- ----
1 abcd
2 fff
Procedure which accepts a parameter and handles exceptions (that's rather poor handling, just to show what to pay attention to):
SQL> create or replace procedure tet_stop_did
2 (par_id in tet_lastgeneratedmaskcode.id%type)
3 is
4 result varchar2(10);
5 lastgeneratedcode tet_lastgeneratedmaskcode.maskedcode%type;
6 begin
7 select maskedcode
8 into lastgeneratedcode
9 from tet_lastgeneratedmaskcode
10 where id = par_id;
11
12 if substr(lastgeneratedcode, 5, 5) != 'ZZZZZ' then
13 result := 'true';
14 else
15 result := 'false';
16 end if;
17
18 dbms_output.put_line('Result = ' || result);
19 exception
20 when no_data_found then
21 dbms_output.put_line('No rows for that ID');
22 when too_many_rows then
23 dbms_output.put_line('Two or more rows for that ID');
24 end tet_stop_did;
25 /
Procedure created.
Testing:
SQL> set serveroutput on
SQL> exec tet_stop_did (1);
Result = false --> here's your result
PL/SQL procedure successfully completed.
SQL>
If you can use SERVEROUTPUT clause to run the procedure you may insert DBMS_OUTPUT in stored procedure code:
CREATE OR REPLACE PROCEDURE TET_STOP_DID
IS
result VARCHAR2(10);
LastGeneratedcode TET_LASTGENERATEDMASKCODE.Maskedcode%TYPE;
BEGIN
select maskedcode into LastGeneratedcode from TET_LASTGENERATEDMASKCODE;
IF (SUBSTR(LastGeneratedcode,5,5) !='ZZZZZ') then
result := 'true';
ELSE
result := 'false';
END IF;
-- Print the output
DBMS_OUTPUT.PUT_LINE(result);
END TET_STOP_DID;
And then from terminal, it runs so:
SQL> SET SERVEROUTPUT ON;
SQL> EXECUTE TET_STOP_DID
false
Thank you
how can i catch error in sql query in block exception? In the example below (division by zero - select (5 / 0) as example from dual), the exception block is not executed.
FUNCTION getData(p_result out integer)
RETURN SYS_REFCURSOR
AS
my_cursor SYS_REFCURSOR;
BEGIN
OPEN my_cursor FOR select (5 / 0) as example from dual;
p_result := 1;
RETURN my_cursor;
exception
WHEN OTHERS THEN
p_result := 0;
END getData;
You're catching the error at the wrong place. It is raised when function is called, not when it is created. Here's an example.
First, your function:
SQL> create or replace
2 FUNCTION getData(p_result out integer)
3 RETURN SYS_REFCURSOR
4 AS
5 my_cursor SYS_REFCURSOR;
6 BEGIN
7 OPEN my_cursor FOR select (5 / 0) as example from dual;
8
9 p_result := 1;
10 RETURN my_cursor;
11
12 exception
13 WHEN OTHERS THEN
14 p_result := 0;
15 END getData;
16 /
Function created.
Calling it; I'm just displaying the error message; you'd do something else.
SQL> declare
2 l_res integer;
3 rc sys_refcursor;
4 l_exam number;
5 begin
6 rc := getdata(l_res);
7 loop
8 fetch rc into l_exam;
9 exit when rc%notfound;
10 dbms_output.put_line(l_exam);
11 end loop;
12 close rc;
13 exception
14 when others then
15 dbms_output.put_line('Error: ' || sqlerrm);
16 end;
17 /
Error: ORA-01476: divisor is equal to zero
PL/SQL procedure successfully completed.
SQL>
-------Just User this function------
------------------------------------
FUNCTION getData(p_result out integer)
RETURN SYS_REFCURSOR
AS
my_cursor SYS_REFCURSOR;
BEGIN
OPEN my_cursor FOR select (5 / NULLIF(0,0)) as example from dual;
p_result := 1;
RETURN my_cursor;
exception
WHEN OTHERS THEN
p_result := 0;
END getData;
Is there any way to assign a select query to local variable in PL/SQL other than select into statement?. Because select into throwing null value exception if the select query returns null value. Thanks
It would be helpful to post your code, but here is an example that should show the behavior you need. Assume there is a table called courses_tbl:
declare
cnumber number := NULL;
CURSOR c1
IS
SELECT course_number
FROM courses_tbl
WHERE course_name = 'XYZ';
BEGIN
open c1;
fetch c1 into cnumber;
if c1%notfound then
-- Do something here if you care about not found.
cnumber := 999; -- whatever
end if;
you can read about cursor attributes here
Seems that you need to use the exception handling as follows:
... -- Your procedure other code
BEGIN
SELECT <COLUMN_NAME> INTO <YOUR_VARIABLE>
FROM .....
WHERE ....
EXCEPTION WHEN NO DATA FOUND THEN
<YOUR_VARIABLE> := NULL;
END;
... -- Your procedure other code
You can use EXECUTE IMMEDIATE...INTO...:
DECLARE
nCnumber NUMBER;
BEGIN
EXECUTE IMMEDIATE 'SELECT CNUMBER FROM COURSES_TBL WHERE CNUMBER = 1'
INTO nCnumber;
DBMS_OUTPUT.PUT_LINE('SELECT #1 : nCnumber = ' || nCnumber);
nCnumber := NULL;
BEGIN
EXECUTE IMMEDIATE 'SELECT CNUMBER FROM COURSES_TBL WHERE CNUMBER = 100'
INTO nCnumber;
DBMS_OUTPUT.PUT_LINE('SELECT #2 : nCnumber = ' || nCnumber);
EXCEPTION
WHEN NO_DATA_FOUND THEN
DBMS_OUTPUT.PUT_LINE('SELECT #2 : NO DATA FOUND');
END;
END;
db<>fiddle here
You've seen how to do it using a cursor or exception handling section (which is - in my opinion - the right way to do it). However, as we're discussing, here's yet another option - an aggregate function. It won't return NO_DATA_FOUND but NULL.
This is what you have now:
SQL> declare
2 l_job emp.job%type;
3 begin
4 select job
5 into l_job
6 from emp
7 where ename = 'Does not exist';
8 end;
9 /
declare
*
ERROR at line 1:
ORA-01403: no data found
ORA-06512: at line 4
This is what you might do:
SQL> declare
2 l_job emp.job%type;
3 begin
4 select max(job)
5 into l_job
6 from emp
7 where ename = 'Does not exist';
8 end;
9 /
PL/SQL procedure successfully completed.
SQL>
So I have a function that accepts a student id and checks to see if the user exists. I created the function without error and I'm trying to store the return variable in a Boolean like this and print the result
SQL> DECLARE
2 tf BOOLEAN;
3 BEGIN
4 EXECUTE tf := valid_stud(5)
5 DBMS_OUTPUT.PUT_LINE(tf);
6 END;
7 /
But this is getting me an error.
ERROR at line 4:
ORA-06550: line 4, column 9:
PLS-00103: Encountered the symbol "TF" when expecting one of the following:
:= . ( # % ; immediate
The symbol "." was substituted for "TF" to continue.
My function is this
CREATE OR REPLACE FUNCTION valid_stud(v_student_id NUMBER) RETURN BOOLEAN
IS
v_id NUMBER;
BEGIN
SELECT student_id
INTO v_id
FROM STUDENT
WHERE student_id = v_student_id;
IF SQL%FOUND THEN
RETURN TRUE;
END IF;
EXCEPTION
WHEN no_data_found THEN RETURN FALSE;
END valid_stud;
/
Here's a demonstration which shows how to do that.
Sample table:
SQL> create table student (
2 student_id number
3 );
Table created.
Function: I removed unnecessary check whether SELECT returned a value; if it did, fine. If not, it'll raise an exception.
SQL> create or replace function valid_stud (
2 v_student_id number
3 ) return boolean is
4 v_id number;
5 begin
6 select student_id into
7 v_id
8 from student
9 where student_id = v_student_id;
10
11 return true;
12 exception
13 when no_data_found then
14 return false;
15 end valid_stud;
16 /
Function created.
Testing:
SQL> set serveroutput on
SQL> declare
2 tf boolean;
3 begin
4 tf := valid_stud(5);
5 if tf then
6 dbms_output.put_line('Student exists');
7 else
8 dbms_output.put_line('Student does not exist');
9 end if;
10 end;
11 /
Student does not exist
PL/SQL procedure successfully completed.
SQL>
I have this piece of code which I want to convert into a function , and call the function in a select statement by passing vendor_site_id from ap_supplier_sites_all. so that I can get the value of vendor_number i.e segment1 of ap_suppliers . here in this piece of code , I have a login to fetch first 6 digits from the column attribute52 of DFF table gecm_dff_ext .
DECLARE
v_ret_val VARCHAR2(30);
v_sup_gsl VARCHAR2(30);
v_vendor_id NUMBER;
BEGIN
v_vendor_id := '${PO.H_VENDOR_ID}';--> vendor_id column from ap_suppliers
IF <condition> = 'Y'
THEN
BEGIN
SELECT SUBSTR(ATTRIBUTE52,1,6)
INTO v_sup_gsl
FROM gecm_dff_ext
WHERE primary_table ='AP_SUPPLIER_SITES_ALL'
AND primary_key = '${PO.H_VENDOR_SITE_ID}';--> This value should be vendor_site_id from ap_supplier_sites_all table
EXCEPTION
WHEN OTHERS THEN
v_sup_gsl := NULL;
END;
BEGIN
IF v_sup_gsl IS NOT NULL THEN
SELECT segment1
INTO v_ret_val
FROM ap_suppliers
WHERE segment1 = v_sup_gsl;
END IF;
EXCEPTION
WHEN OTHERS THEN
v_ret_val := '';
END;
END IF;
IF v_sup_gsl IS NULL THEN
BEGIN
SELECT SEGMENT1
INTO v_ret_val
FROM ap_suppliers
WHERE vendor_id=v_vendor_id;
EXCEPTION
WHEN OTHERS THEN
v_ret_val := '';
END;
END IF;
:return_value:=v_ret_val;
END;
This is a simplified example: the following SELECT returns department name for a certain department number:
SQL> select dname
2 from dept
3 where deptno = &par_deptno;
Enter value for par_deptno: 10
DNAME
--------------
ACCOUNTING
SQL>
So, how to convert it to a function? By using a proper syntax, declaring a return variable, fetching into it and - returning the result:
SQL> create or replace function f_test (par_deptno in dept.deptno%type)
2 return dept.dname%type
3 is
4 retval dept.dname%type;
5 begin
6 select dname
7 into retval
8 from dept
9 where deptno = par_deptno;
10
11 return retval;
12 exception
13 when no_data_found then
14 return null;
15 end;
16 /
Function created.
SQL> select f_test(10) from dual;
F_TEST(10)
---------------------------------------------------------------------------
ACCOUNTING
SQL> select f_test(999) from dual;
F_TEST(999)
---------------------------------------------------------------------------
SQL>
This is what you should do. It seems that you are returning the v_ret_val, so - your code might look like this:
create or replace function f_test (par_vendor_id po.h_vendor_id%type)
return ap_suppliers.segment1%type
is
v_ret_val ap_suppliers.segment1%type;
begin
if <condition> = 'Y' then
...
end if;
return v_ret_val;
end;