Printing a statement in stored procedure - oracle

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

Related

Error passing an Oracle cursor when trying to test print its contents

We're using Oracle 12c.
Passing a cursor from a procedure. Trying to test print its contents.
I get the following error message:
ORA-01001: invalid cursor
ORA-06512: at line 25
Why is the cursor invalid?
Here's the code.
SET SERVEROUTPUT ON
--VARIABLE X REFCURSOR;
DECLARE
RUN_DATE VARCHAR2 (10);
D_XMAS_NY VARCHAR2 (10);
PO_ERROR_CODE_N NUMBER;
PO_ERROR_MESSAGE_C VARCHAR2 (32767);
PO_REF_CUR SLD_COMMON_PKG.PG_COMMON_REFCUR;
V_VAL SLDPROC.t_sld_gic_repo_nonrepo_rec%ROWTYPE;
BEGIN
RUN_DATE := '2022-07-27';
D_XMAS_NY := '9999-12-30';
PO_ERROR_CODE_N := NULL;
PO_ERROR_MESSAGE_C := NULL;
-- PO_REF_CUR := NULL;
SLDPROC.SP_SLD_GEN_GIC_REINV_DET (RUN_DATE,
D_XMAS_NY,
PO_ERROR_CODE_N ,
PO_ERROR_MESSAGE_C,
PO_REF_CUR);
LOOP
FETCH PO_REF_CUR INTO V_VAL;
EXIT WHEN PO_REF_CUR%NOTFOUND;
/*Notice the DBMS_OUTPUT line is commented out. So at this point, Oracle is just running through the cursor.*/
--DBMS_OUTPUT.PUT_LINE( V_VAL.d_inc_dt );
END LOOP;
CLOSE PO_REF_CUR;
END;
I get the following error message:
ORA-01001: invalid cursor
ORA-06512: at line 25
The Procedure SLDPROC.SP_SLD_GEN_GIC_REINV_DET compiles correctly and the cursor inside the procedure is correct. Finally when I run this procedure without any trace of the Cursor Loop it finishes correctly. It's when I try to list out the contents of the cursor.
The contents of the cursor consist of 1 giant column with all the columns from a table concatenated together like this.
OPEN po_ref_cur FOR
SELECT c_run_type
|| ','
|| TO_CHAR(d_inc_dt, 'DD/MM/YYYY')
|| ','
|| lend_agnt
|| ','
|| trim(ACCNT)
|| ','
|| NVL(trim(DAY_CT), '<NULL>') -- DAY_CT
|| ','
|| NVL(trim(REPOCP_LEI_CODE), '<NULL>') -- REPOCP_LEI_CODE
|| ','
|| NVL(trim(REPOCP_BR_DESC), '<NULL>')
FROM t_sld_gic_repo_nonrepo_rec
ORDER BY c_run_type,d_inc_dt, NVL(issuer_repocp, 'ZZ');
SP_SLD_GEN_GIC_REINV_DET procedure's last parameter should be OUT, returning a ref cursor. Is it?
Because, if I try to mimic what you did, that code works.
Sample procedure:
SQL> CREATE OR REPLACE PROCEDURE SP_SLD_GEN_GIC_REINV_DET (
2 par_rc OUT SYS_REFCURSOR
3 ) IS
4 BEGIN
5 OPEN par_rc FOR SELECT dname FROM dept;
6 END;
7 /
Procedure created.
SQL>
Your anonymous PL/SQL block (slightly modified):
SQL> SET SERVEROUTPUT ON
SQL> DECLARE
2 run_date VARCHAR2(10);
3 d_xmas_ny VARCHAR2(10);
4 po_error_code_n NUMBER;
5 po_error_message_c VARCHAR2(32767);
6 po_ref_cur SYS_REFCURSOR;-- SLD_COMMON_PKG.PG_COMMON_REFCUR;
7 v_val VARCHAR2(200); --SLDPROC.t_sld_gic_repo_nonrepo_rec%ROWTYPE;
8 BEGIN
9 run_date := '2022-07-27';
10 d_xmas_ny := '9999-12-30';
11 po_error_code_n := NULL;
12 po_error_message_c := NULL;
13
14 -- PO_REF_CUR := NULL;
15 -- SLDPROC.SP_SLD_GEN_GIC_REINV_DET (RUN_DATE,
16 -- D_XMAS_NY,
17 -- PO_ERROR_CODE_N ,
18 -- PO_ERROR_MESSAGE_C,
19 -- PO_REF_CUR);
20 SP_SLD_GEN_GIC_REINV_DET (po_ref_cur);
21 LOOP
22 FETCH po_ref_cur INTO v_val;
23 EXIT WHEN po_ref_cur%notfound;
24 /*Notice the DBMS_OUTPUT line is commented out. So at this point, Oracle is just running through the cursor.*/
25 DBMS_OUTPUT.PUT_LINE(V_VAL);
26 END LOOP;
27 CLOSE po_ref_cur;
28 END;
29 /
ACCOUNTING
RESEARCH
SALES
OPERATIONS
PL/SQL procedure successfully completed.
SQL>

PL/SQL simple task

I want to create a procedure whith two arguments. It should check if the arguments are values of family table and if both are not the same value.
I planned this code but I noted it doesn't work
create or replace procedure Compare(first_value values.value%type, second_value values.value%type)
as
begin
if second_value not exists(select values from family) then
dbms.output.put_line('The second values doesn't exist');
else if first_value = second_value then
dbms.output.put_line('Both values are the same');
else
dbms.output.put_line('Great Job');
end if;
end;
/
I'll appreciate any help.
Here's one option.
SQL> set serveroutput on
Sample data:
SQL> select * from family;
C_VALUES
--------
Little
Foot
Procedure:
SQL> create or replace procedure p_compare
2 (par_value_1 in family.c_values%type,
3 par_value_2 in family.c_values%type
4 )
5 as
6 l_cnt_1 number;
7 l_cnt_2 number;
8 begin
9 select count(*)
10 into l_cnt_1
11 from family
12 where c_values = par_value_1;
13
14 select count(*)
15 into l_cnt_2
16 from family
17 where c_values = par_value_2;
18
19 if l_cnt_1 = 0 then
20 dbms_output.put_line('The first value does not exist');
21 elsif l_cnt_2 = 0 then
22 dbms_output.put_line('The second value does not exist');
23 elsif par_value_1 = par_value_2 then
24 dbms_output.put_line('Both values are the same');
25 else
26 dbms_output.put_line('Great job');
27 end if;
28 end;
29 /
Procedure created.
Testing:
SQL> exec p_compare('Little', 'Foot');
Great job
PL/SQL procedure successfully completed.
SQL> exec p_compare('Little', 'Little');
Both values are the same
PL/SQL procedure successfully completed.
SQL> exec p_compare('Big', 'Foot');
The first value does not exist
PL/SQL procedure successfully completed.
SQL>
Here is a not so well written, but somehow alternative take on the task:
CREATE OR REPLACE PROCEDURE COMPARE(FIRST_VALUE VALUES.VALUE%TYPE,
SECOND_VALUE VALUES.VALUE%TYPE)
AS
l_message VARCHAR2(40);
BEGIN
SELECT CASE WHEN test_val < 2 THEN 'The first value does not exist'
WHEN test_val < 3 THEN 'The second value does not exist'
WHEN first_value = second_value THEN 'Both values are the same'
ELSE 'Great job'
END
INTO l_message
FROM (SELECT NVL(SUM(val),0) AS test_val
FROM (SELECT 2 AS val
FROM family
WHERE val = first_value
AND ROWNUM = 1
UNION ALL
SELECT 1 AS val
FROM family
WHERE val = second_value
AND ROWNUM = 1));
DBMS_OUTPUT.PUT_LINE(l_message);
END;
/

Need to find the number of times PLSQL function gets executed

There is a requirement from client side that after function get executed more than 2 times then its output should be concatinated with some string and this function is inside a package .
for example...
function get called 7 times from package (its a backend job which executed automatically) and returns 'abc' but when the job runs for the 3rd time i want output 'abcde'.
One option is to create a separate log table and insert a row for each of function calls; then - within a function - check how many times it was invoked and return appropriate output. Something like this:
Log table:
SQL> CREATE TABLE flog
2 (
3 cuser VARCHAR2 (30),
4 sid NUMBER
5 );
Table created.
Package:
SQL> CREATE OR REPLACE PACKAGE pkg_test
2 IS
3 FUNCTION f_test
4 RETURN VARCHAR2;
5
6 PROCEDURE p_test;
7 END;
8 /
Package created.
Package body:
SQL> CREATE OR REPLACE PACKAGE BODY pkg_test
2 IS
3 FUNCTION f_test
4 RETURN VARCHAR2
5 IS
6 l_cnt NUMBER;
7 retval VARCHAR2 (10);
8 BEGIN
9 SELECT COUNT (*)
10 INTO l_cnt
11 FROM flog
12 WHERE cuser = USER
13 AND sid = SYS_CONTEXT ('USERENV', 'SID');
14
15 retval := CASE WHEN l_cnt <= 2 THEN 'abc' ELSE 'abc' || 'de' END;
16 RETURN retval;
17 END;
18
19 PROCEDURE p_test
20 IS
21 BEGIN
22 FOR i IN 1 .. 3
23 LOOP
24 INSERT INTO flog (cuser, sid)
25 VALUES (USER, SYS_CONTEXT ('USERENV', 'SID'));
26
27 DBMS_OUTPUT.put_line ('Execution #' || i || ', result = ' || f_test);
28 END LOOP;
29 END;
30 END pkg_test;
31 /
Package body created.
Testing:
SQL> SET SERVEROUTPUT ON
SQL> EXEC pkg_test.p_test;
Execution #1, result = abc
Execution #2, result = abc
Execution #3, result = abcde
PL/SQL procedure successfully completed.
SQL>

How do I display the result of the procedure Oracle?

In my code there is a function that displays a message on the screen. But when I start, I do not see the result.
I guess this line does not work.
UPDATE EMPLOYEES SET COMMISSION_PCT = NEWCOMMISSION WHERE LINES.COMMISSION_PCT IS NULL;
Is it so?
I'm using Oracle XE 112, I'm using a browser.
Full code
CREATE OR replace PROCEDURE Zadacha31
IS
lengthphone INTEGER;
substrcommission VARCHAR2(50);
newcommission FLOAT;
info FLOAT;
CURSOR get_data IS
SELECT *
FROM employees;
BEGIN
FOR lines IN get_data LOOP
IF lines.commission_pct IS NULL THEN
lengthphone := Length(lines.phone_number);
substrcommission := Substr(lines.phone_number, lengthphone - 1, 2);
newcommission := To_number('.'
||substrcommission);
UPDATE employees
SET commission_pct = newcommission
WHERE lines.commission_pct IS NULL;
dbms_output.Put_line(lines.commission_pct);
END IF;
END LOOP;
END;
Try executing set serveroutput on before you run the procedure
It seems that you have an error in your logic.
Consider. You execute the UPDATE only if this test is true:
IF lines.commission_pct IS NULL THEN
Your code calculates a new commission and updates all the records (hint: this is probably not what you want but is irrelevant to your question).
UPDATE employees
SET commission_pct = newcommission
WHERE lines.commission_pct IS NULL;
However, your output is displaying the unamended original value and nothing else.
dbms_output.Put_line(lines.commission_pct);
So your procuedure may well be updating and displaying something, but all it's displaying is a NULL so it looks as though nothing is occuring.
To solve this, use the new value:
dbms_output.Put_line('new commission = ' ||newcommission);
To solve the updating all records use a better where condition:
UPDATE employees e
SET e.commission_pct = newcommission
WHERE e.emp_id = lines.emp_id; -- or whatever the PK is
And why not make the output message more useful while we're at it?
dbms_output.Put_line('emp# '|| lines.emp_id||' new commission = ' ||newcommission);
This is how it looks like in SQL*Plus:
SQL> CREATE OR replace PROCEDURE Zadacha31
2 IS
3 lengthphone INTEGER;
4 substrcommission VARCHAR2(50);
5 newcommission FLOAT;
6 info FLOAT;
7 CURSOR get_data IS
8 SELECT *
9 FROM employees;
10 BEGIN
11 dbms_output.put_line('Procedure starts here');
12 FOR lines IN get_data LOOP
13 IF lines.commission_pct IS NULL THEN
14 dbms_output.put_line('commision_pct IS NOT NULL!');
15
16 lengthphone := Length(lines.phone_number);
17
18 substrcommission := Substr(lines.phone_number, lengthphone - 1, 2);
19
20 newcommission := To_number('.'
21 ||substrcommission);
22
23 UPDATE employees
24 SET commission_pct = newcommission
25 WHERE lines.commission_pct IS NULL;
26
27 dbms_output.Put_line(lines.commission_pct);
28 END IF;
29 END LOOP;
30 dbms_output.put_line('Procedure ends here');
31 END;
32 /
Procedure created.
SQL>
SQL> set serveroutput on
SQL>
SQL> begin
2 zadacha31;
3 end;
4 /
Procedure starts here
Procedure ends here
PL/SQL procedure successfully completed.
SQL>
It appears that the procedure finished correctly, but - nothing was displayed nor updated. Let's check why:
SQL> select count(*) from employees where commission_pct is null;
COUNT(*)
----------
0
SQL>
Does it ring a bell?
As of your environment: it looks like Apex' SQL Workshop, while data you use is contained in the HR schema. If that's so, you're right - you don't need to SET SERVEROUTPUT ON there, it is enabled by default.
Though, that wasn't your problem, but the fact that no employee has COMMISSION_PCT IS NULL.

Assigning output parameter from Stored Procedure in oracle

Please help me with the following scenario
I need to call a Stored Procedure inside another one. the inner SP would return a number value which I need to store it in a local variable.
rough code
AssignSpResult NUMBER;
AssignSpResult = SPtobecalled(Param1,Param2, OutParam);
This syntax is most probably wrong, so please help correct it
Here is an example of how it might be:
HR\XE> create or replace procedure Proc1(p_out out number)
2 is
3 begin
4 p_out := 123;
5* end;
HR\XE> /
Procedure created.
HR\XE> create or replace procedure Proc2
2 is
3 l_val number;
4 begin
5 Proc1(l_val);
6 dbms_output.put_line('Here is a value returned by Proc1: ' || to_char(l_val));
7 end;
8 /
Procedure created.
HR\XE> set serveroutput on;
HR\XE> exec Proc2;
Here is a value returned by Proc1: 123
PL/SQL procedure successfully completed
Depending on your needs it might be more convenient to use functions to return a result of a procedural processing of data. Here is an example:
HR\XE> create or replace function F1 return number
2 is
3 l_ret_value number;
4 begin
5 l_ret_value := 123;
6 return l_ret_value;
7 end;
HR\XE> /
Function created.
HR\XE> create or replace procedure Proc3
2 is
3 l_val number;
4 begin
5 l_val := F1;
6 dbms_output.put_line('Value returned by the F1 function: ' ||
To_Char(l_val));
7 -- Or
8 dbms_output.put_line('Value returned by the F1 function: ' || To_Char(F1));
9 end;
HR\XE> /
Procedure created.
HR\XE> set serveroutput on;
HR\XE> exec proc3;
Value returned by the F1 function: 123
Value returned by the F1 function: 123
PL/SQL procedure successfully completed.
HR\XE>
A stored procedure does not return a value it takes IN, OUT or IN OUT parameters. So probably your have to call:
SPtobecalled(Param1,Param2, AssignSpResult );

Resources