ORA-00900: invalid SQL statement- when run a package in oracle 12c - oracle

I am using Oracle 12c database and trying to run a package using SQL commands.
CREATE OR REPLACE PACKAGE "PK_CP_OTM" as
FUNCTION F_CP_OPTIMIZATION (
v_current_day IN VARCHAR2,
v_branch_code IN VARCHAR2)
RETURN VARCHAR2;
END PK_CP_OTM;
When I try to execute it using:
DECLARE
BEGIN
EXECUTE IMMEDIATE PK_CP_OTM.F_CP_OPTIMIZATION('20190409','BRNCD001');
END;
It shows:
ORA-00900: invalid SQL statement
ORA-06512: at line 3
00900. 00000 - "invalid SQL statement"
Thanks for your help.

As #Littlefoot said, you don't need dynamic SQL here, you can make a static call; but as you are calling a function you do need somewhere to put the result of the call:
declare
l_result varchar2(30); -- make it a suitable size
begin
l_result := pk_cp_otm.f_cp_optimization('20190409','BRNCD001');
end;
/
In SQL*Plus, SQL Developer and SQLcl you can use the execute client command (which might have caused some confusion) and a bind variable for the result:
var result varchar2(30);
exec :result := pk_cp_otm.f_cp_optimization('20190409','BRNCD001');
print result

There's nothing dynamic here, so - why would you use dynamic SQL at all?
Anyway: if you insist, then you'll have to select the function into something (e.g. a local variable). Here's an example
First, the package:
SQL> set serveroutput on
SQL>
SQL> create or replace package pk_cp_otm
2 as
3 function f_cp_optimization (v_current_day in varchar2,
4 v_branch_code in varchar2)
5 return varchar2;
6 end pk_cp_otm;
7 /
Package created.
SQL> create or replace package body pk_cp_otm
2 as
3 function f_cp_optimization (v_current_day in varchar2,
4 v_branch_code in varchar2)
5 return varchar2
6 is
7 begin
8 return 'Littlefoot';
9 end;
10 end pk_cp_otm;
11 /
Package body created.
How to call the function?
SQL> declare
2 l_result varchar2 (20);
3 begin
4 execute immediate
5 'select pk_cp_otm.f_cp_optimization (''1'', ''2'') from dual'
6 into l_result;
7
8 dbms_output.put_line ('result = ' || l_result);
9 end;
10 /
result = Littlefoot
PL/SQL procedure successfully completed.
SQL>

Related

ORACLE - can i pass cursor in a parameter and how to use it?

Here is one of oracle procedure. There is a cursor called r_ba.
DECLARE
r_ba SYS_REFCURSOR;
BEGIN
OPEN r_ba FOR
SELECT head.*,
line.jenis_pekerjaan,
line.deskripsi_pekerjaan,
line.akun,
line.rate_ppn,
line.dpp,
line.ppn,
line.total_realisasi,
line.major,
line.minor,
line.sla
FROM idm_ap_mtc_acl_header_tmp head, idm_ap_mtc_acl_lines_tmp line
WHERE head.no_ba = line.no_ba AND head.req_id = line.req_id AND head.req_id = n_req_id;
create_invoice_ap2 (
p_org_id => p_org_id,
p_user_id => p_user_id,
p_branch_code => v_branch_code,
r_ba => r_ba);
END;
and how call that cursor in this procedure ?
PROCEDURE create_invoice_ap2 (p_org_id IN NUMBER,
p_user_id IN NUMBER,
p_branch_code IN VARCHAR2,
r_ba IN SYS_REFCURSOR)
IS
r_tax_info rt_tax_info;
rt_ba SYS_REFCURSOR;
BEGIN
------------ setup ------------
r_tax_info := get_tax_code (
p_date => rt_ba.tgl_ba,
p_group_tax_name => rt_ba.tax_name,
p_ppn_rate => rt_ba.ppn_rate,
p_dc_code => rt_ba.dc_code);
END;
oracle give me error
[Error] PLS-00487 (707: 64): PLS-00487: Invalid reference to variable 'RT_BA'
Anyone could suggest me a way to accomplish this?
Thanks
If you're passing refcursor into a parameter named r_ba, then - I believe - you should use it, not declare another (rt_ba):
PROCEDURE create_invoice_ap2 (p_org_id IN NUMBER,
p_user_id IN NUMBER,
p_branch_code IN VARCHAR2,
r_ba IN SYS_REFCURSOR)
IS
r_tax_info rt_tax_info;
-- rt_ba SYS_REFCURSOR; --> you don't need it
BEGIN
------------ setup ------------
r_tax_info := get_tax_code (
p_date => r_ba.tgl_ba,
p_group_tax_name => r_ba.tax_name,
p_ppn_rate => r_ba.ppn_rate,
p_dc_code => r_ba.dc_code);
END; ----
^
|
r_ba, not rt_ba
Also, note that you should generally avoid select * because it can lead to ambiguity if there are columns with the same name as columns in other tables, so Oracle doesn't know which one you want to use.
The same goes for typos; for example, in anonymous PL/SQL block you're selecting line.rate_ppn, while procedure uses p_ppn_rate => r_ba.ppn_rate (rate_ppn vs. ppn_rate). Maybe it is OK because there's ppn_rate column in head table (which is in select head.*) but - once again - that's difficult to debug.
Furthermore, you can't use refcursor that way - you have to fetch from it. Have a look at example based on Scott's sample schema. Here's a procedure that accepts refcursor as a parameter and does something with it:
SQL> create or replace procedure p_test (r_ba in sys_refcursor)
2 is
3 l_dname varchar2(20);
4 begin
5 l_dname := r_ba.dname;
6 end;
7 /
Warning: Procedure created with compilation errors.
SQL> show err
Errors for PROCEDURE P_TEST:
LINE/COL ERROR
-------- -----------------------------------------------------------------
5/3 PL/SQL: Statement ignored
5/19 PLS-00487: Invalid reference to variable 'R_BA'
SQL>
See? The same error you got. Therefore, fetch:
SQL> create or replace procedure p_test (r_ba in sys_refcursor)
2 is
3 l_row dept%rowtype;
4 begin
5 loop
6 fetch r_ba into l_row;
7 exit when r_ba%notfound;
8 dbms_output.put_line(l_row.deptno ||', '|| l_row.dname ||', '|| l_row.loc);
9 end loop;
10 end;
11 /
Procedure created.
SQL> declare
2 r_ba sys_refcursor;
3 begin
4 open r_ba for select deptno, dname, loc from dept;
5 p_test (r_ba);
6 end;
7 /
10, ACCOUNTING, NEW YORK
20, RESEARCH, DALLAS
30, SALES, CHICAGO
40, OPERATIONS, BOSTON
PL/SQL procedure successfully completed.
SQL>
Now it is OK.
I don't know what you're doing with r_tax_info, how many rows refcursor contains (whether you need to use a loop or not), but - that's the general idea. Fetch first, use it next.

procedure compiling in oracle is not working

I have written below procedure in oracle but its getting compiled with error.
CREATE OR REPLACE PROCEDURE PROC_MIGRATE_ONEIBER
AS
BEGIN
-- EXECUTE PROCEDURE ONEFIBER_LNK_MIGRATE;
execute ONEFIBER_LNK_MIGRATE;
execute ONEFIBER_LNK_MIGRATE_CITY;
execute ONEFIBER_LNK_MIGRATE_NLDC;
END;
-- NULL;
END PROC_MIGRATE_ONEIBER;
I have to execute 3 procedures in one main procedure without any IN or OUT parameters. But its not working
Just remove the execute keyword. Whenever you want to call another procedure within the procedure you can directly use the procedure name and parameters, If any.
CREATE OR REPLACE PROCEDURE PROC_MIGRATE_ONEIBER AS
BEGIN
-- EXECUTE PROCEDURE ONEFIBER_LNK_MIGRATE;
ONEFIBER_LNK_MIGRATE;
ONEFIBER_LNK_MIGRATE_CITY;
ONEFIBER_LNK_MIGRATE_NLDC;
--END;
-- NULL;
END PROC_MIGRATE_ONEIBER;
/
Update: Check this small code of how it should be. All procedures created in this answer are just for demo. (Make sure that the procedure that you are calling is not INVALID)
SQL>
SQL> CREATE OR REPLACE PROCEDURE ONEFIBER_LNK_MIGRATE AS
2 BEGIN
3 NULL;
4 END;
5 /
Procedure created.
SQL>
SQL> CREATE OR REPLACE PROCEDURE ONEFIBER_LNK_MIGRATE_CITY AS
2 BEGIN
3 NULL;
4 END;
5 /
Procedure created.
SQL>
SQL> CREATE OR REPLACE PROCEDURE ONEFIBER_LNK_MIGRATE_NLDC AS
2 BEGIN
3 NULL;
4 END;
5 /
Procedure created.
SQL>
SQL> CREATE OR REPLACE PROCEDURE PROC_MIGRATE_ONEIBER AS
2 BEGIN
3 ONEFIBER_LNK_MIGRATE;
4 ONEFIBER_LNK_MIGRATE_CITY;
5 ONEFIBER_LNK_MIGRATE_NLDC;
6 END PROC_MIGRATE_ONEIBER;
7 /
Procedure created.
SQL>

when try to excure procedure it said compliation error in oracle?

I try to write select procedure in oracle.but it compile success, when I try to execute it given error.
set serveroutput on;
CREATE OR REPLACE PROCEDURE retrieve_decrypt(
custid in NUMBER,
column_name in VARCHAR2,
test_value OUT VARCHAR2
)
AS
BEGIN
-- enc_dec.decrypt(column_name,password) into test_value from employees where custid=5;
COMMIT;
END;
/
set serveroutput on;
EXEC retrieve_decrypt(5,'creditcardno');
the error says ,
This is your procedure:
SQL> create or replace procedure retrieve_decrypt
2 (custid in number,
3 column_name in varchar2,
4 test_value out varchar2
5 )
6 as
7 begin
8 -- your code goes here
9 null;
10 end;
11 /
Procedure created.
SQL>
This is how you call it (and get the error):
SQL> exec retrieve_decrypt(5, 'creditcardno');
BEGIN retrieve_decrypt(5, 'creditcardno'); END;
*
ERROR at line 1:
ORA-06550: line 1, column 7:
PLS-00306: wrong number or types of arguments in call to 'RETRIEVE_DECRYPT'
ORA-06550: line 1, column 7:
PL/SQL: Statement ignored
SQL>
The cause of the error is:
the procedure contains 3 parameters:
2 of them are IN - you provided their values
1 of them is OUT - you didn't provide it and got the error
Here's what you should have done: as the 3rd parameter is OUT, you'll have to DECLARE it:
SQL> declare
2 l_out varchar2(20);
3 begin
4 retrieve_decrypt(5, 'creditcardno', l_out);
5 end;
6 /
PL/SQL procedure successfully completed.
SQL>
EXEC you used is a SQL*Plus command so it might not work everywhere; DECLARE-BEGIN-END block will so I'd suggest you use it.
Alternatively, in SQL*Plus, it could be rewritten as
SQL> var l_out varchar2
SQL>
SQL> exec retrieve_decrypt(5, 'creditcardno', :l_out);
PL/SQL procedure successfully completed.
SQL>
but - once again - you'd better use DECLARE-BEGIN-END PL/SQL block.
The initial error is:
wrong number or types of arguments in call to 'RETRIEVE_DECRYPT'
The procedure requires 3 parameters. You are only passing 2 (or apparently only 1, in the attempt that generated the error message shown).
Why do you also see the message "Usually a PL/SQL compilation error"? The EXEC command in SQLPlus creates a PL/SQL block containing the text you provide, and sends that to Oracle for execution. Oracle attempts to compile that PL/SQL block (just like it compiles the procedure when you create it). In this case, the compilation fails because of the mismatch in the number of arguments.

PL/SQL Trying to execute a very simple procedure

I know this is a very stupid question, but I just can't get this to work. I get an error saying that identifier hello must be declared
CREATE OR REPLACE PROCEDURE hello (p_name IN VARCHAR2)
IS
BEGIN
dbms_output.put_line (‘Welcome '|| p_name);
END hello;
/
EXECUTE hello('JOHN');
Everything's fine, except the first single quote in DBMS_OUTPUT call:
SQL> CREATE OR REPLACE PROCEDURE hello (p_name IN VARCHAR2)
2 IS
3 BEGIN
4 dbms_output.put_line ('Welcome '|| p_name);
5 END hello; -- ^ change this one
6 /
Procedure created.
SQL> EXECUTE hello('JOHN');
Welcome JOHN
PL/SQL procedure successfully completed.
SQL>

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