Return value from Oracle stored procedure - oracle

I have a stored procedure in Oracle. I want that if it updates the record successfully the it returns a return value 1 else 0. Let me know how can I do it. I am working with Angular, Asp.net, WebAPi and Oracle database.
Thanks in advance. My code is as follows:
CREATE OR REPLACE Procedure NML.AddProductProcedure(V_CRD_COD In varchar2,
V_ITM_COD In varchar2,
V_SRL_NUM In varchar2,
V_UOM_ABR IN varchar2,
V_QTD_RTE IN varchar2,
V_QTY_PRC In varchar2,
V_QTN_NUM IN varchar2,
V_PMT_FLG IN varchar2,
V_TAX_FLG IN varchar2,
V_DLV_FLG IN varchar2)
IS
BEGIN
UPDATE NML.pgi_00_13
SET UOM_ABR = V_UOM_ABR,
QTD_RTE = V_QTD_RTE,
QTY_PRC = V_QTY_PRC,
QTN_NUM = V_QTN_NUM,
PMT_FLG = V_PMT_FLG,
TAX_FLG = V_TAX_FLG,
DLV_FLG = V_DLV_FLG
WHERE
CRD_COD = V_CRD_COD
AND ITM_COD = V_ITM_COD
AND SRL_NUM = V_SRL_NUM;
END;

You can define an OUT variable from the procedure that gets set to 1 on successful completion or 0 from an EXCEPTION.
CREATE OR REPLACE PROCEDURE nml.addproductprocedure (
p_crd_cod IN VARCHAR2,
p_itm_cod IN VARCHAR2,
p_srl_num IN VARCHAR2,
p_uom_abr IN VARCHAR2,
p_qtd_rte IN VARCHAR2,
p_qty_prc IN VARCHAR2,
p_qtn_num IN VARCHAR2,
p_pmt_flg IN VARCHAR2,
p_tax_flg IN VARCHAR2,
p_dlv_flg IN VARCHAR2,
p_status OUT NUMBER --use this variable
)
IS
BEGIN
UPDATE nml.pgi_00_13
SET uom_abr = p_uom_abr,
qtd_rte = p_qtd_rte,
qty_prc = p_qty_prc,
qtn_num = p_qtn_num,
pmt_flg = p_pmt_flg,
tax_flg = p_tax_flg,
dlv_flg = p_dlp_flg
WHERE crd_cod = p_crd_cod AND itm_cod = p_itm_cod AND srl_num = p_srl_num;
p_status := 1;
EXCEPTION
WHEN OTHERS THEN
p_status := 0;
END;
/
Your calling block must define OUT parameters as shown here : How to return oracle output parameters from a stored procedure in .NET

What's your definition of "success"? At the moment if your procedure throws an exception it failed otherwise it succeeded. Is that not good enough?
You could extend the signature of the procedure with a parameter which tells you how many records were updated...
CREATE OR REPLACE Procedure NML.AddProductProcedure(
V_CRD_COD In varchar2,
V_ITM_COD In varchar2,
V_SRL_NUM In varchar2,
V_UOM_ABR IN varchar2,
V_QTD_RTE IN varchar2,
V_QTY_PRC In varchar2,
V_QTN_NUM IN varchar2,
V_PMT_FLG IN varchar2,
V_TAX_FLG IN varchar2,
V_DLV_FLG IN varchar2,
p_updated_cnt out pls_integer
)IS
BEGIN
Update NML.pgi_00_13
set
UOM_ABR=V_UOM_ABR,
QTD_RTE=V_QTD_RTE,
QTY_PRC=V_QTY_PRC,
QTN_NUM=V_QTN_NUM,
PMT_FLG=V_PMT_FLG,
TAX_FLG=V_TAX_FLG,
DLV_FLG=V_DLV_FLG
Where CRD_COD=V_CRD_COD
AND ITM_COD=V_ITM_COD
AND SRL_NUM=V_SRL_NUM;
-- count of rows updated by preceding statement
p_updated_cnt := sql%rowcount;
END;
Note that you could instead pass a flag or 1 or 0 as shown in #Kaushik solution but this is an anti-pattern. Because:
It returns success when the statement updates zero rows, which is a technical success but probably not a successful completion from a business perspective.
A calling program can choose to ignore the flag value, whereas it must handle a propagated exception.
If the calling program wants to act when the flag value indicates failure it has no idea why the called procedure failed. Exceptions on the other hand are usually specific enough to support decision making.
Just want retun 1 when it succeded to update the record
Well you could do this:
CREATE OR REPLACE Procedure NML.AddProductProcedure(
V_CRD_COD In varchar2,
V_ITM_COD In varchar2,
V_SRL_NUM In varchar2,
V_UOM_ABR IN varchar2,
V_QTD_RTE IN varchar2,
V_QTY_PRC In varchar2,
V_QTN_NUM IN varchar2,
V_PMT_FLG IN varchar2,
V_TAX_FLG IN varchar2,
V_DLV_FLG IN varchar2,
p_updated_flag out pls_integer
)IS
BEGIN
Update NML.pgi_00_13
set
UOM_ABR=V_UOM_ABR,
QTD_RTE=V_QTD_RTE,
QTY_PRC=V_QTY_PRC,
QTN_NUM=V_QTN_NUM,
PMT_FLG=V_PMT_FLG,
TAX_FLG=V_TAX_FLG,
DLV_FLG=V_DLV_FLG
Where CRD_COD=V_CRD_COD
AND ITM_COD=V_ITM_COD
AND SRL_NUM=V_SRL_NUM;
if sql%rowcount > 0 then
p_update_flag := 1;
else
p_update_flag := 0;
end if;
END;
This will still hurl if there's an exception - which is a good thing - but distinguishes between updating zero records and one record (or more).

Related

Error(12,5): PLS-00103: Encountered the symbol "LC_SQLERRM" when expecting one of the following: language

CREATE OR REPLACE PACKAGE APPS.XX_PROC_ADI_test AS
PROCEDURE XX_INS_DATA_ADI (
p_primary_uom_flag VARCHAR2,
p_list_line_type_code VARCHAR2,
p_price_break_type_code VARCHAR2,
p_arithmetic_operator VARCHAR2,
p_operand NUMBER,
p_start_date_active DATE,
p_end_date_active DATE,
p_product_precedence NUMBER
);
END;
SET VERIFY OFF
WHENEVER SQLERROR EXIT FAILURE ROLLBACK;
CREATE OR REPLACE PACKAGE APPS.XX_PROC_ADI_test AS
PROCEDURE XX_INS_DATA_ADI (
p_primary_uom_flag VARCHAR2,
p_list_line_type_code VARCHAR2,
p_price_break_type_code VARCHAR2,
p_arithmetic_operator VARCHAR2,
p_operand NUMBER,
p_start_date_active DATE,
p_end_date_active DATE,
p_product_precedence NUMBER
)IS
lc_sqlerrm VARCHAR2(2000);
lc_error_msg VARCHAR2 (2000);
l_responsibility_id NUMBER := apps.fnd_global.resp_id;
l_resp_application_id NUMBER := apps.fnd_global.resp_appl_id;
l_org_id NUMBER := apps.fnd_global.org_id;
l_user_id NUMBER := apps.fnd_global.user_id;
BEGIN
INSERT INTO QP_LIST_LINES(
primary_uom_flag,
list_line_type_code,
price_break_type_code,
arithmetic_operator,
operand,
start_date_active,
end_date_active,
product_precedence
)
VALUES (
p_primary_uom_flag,
p_list_line_type_code,
p_price_break_type_code,
p_arithmetic_operator,
p_operand,
p_start_date_active,
p_end_date_active,
p_product_precedence
);
COMMIT;
EXCEPTION WHEN OTHERS THEN
lc_sqlerrm := SUBSTR(SQLERRM,1,1999);
raise_application_error (-20001, 'OTHER_EXCEPTION - MSG | ' || lc_sqlerrm);
END;
END XX_INS_DATA_ADI;
END;
If you're going to use this (and your tool supports it), use it at the beginning:
SET VERIFY OFF
WHENEVER SQLERROR EXIT FAILURE ROLLBACK;
Then create
package specification first
package body next
create or replace package xx_proc_adi_test as
procedure xx_ins_data_adi(...);
end xx_proc_adi_test;
/
create or replace package BODY xx_proc_adi_Test as
procedure xx_ins_data_adi(...) is
...
begin
...
exception
...
end xx_ins_data_adi;
end xx_proc_adi_test;
/

How to create function based on this requirement?

HOW TO EXECUTE PACKAGED FUNCTION IN ANONYMOUS BLOCK?
CREATE OR REPLACE FUNCTION function_name(n_fdo number, n_perc varchar2,
n_rating varchar2,
n_oto varchar2,
n_rate varchar2,
n_vlore varchar2,
n_prdotto varchar2,
n_scrd varchar2,
n_retail varchar2,
n_porto varchar2)Return NUMBER;
That's function's description. It accepts number of parameters, all of them are obligatory (as they don't have default value).
As you want to all it from anonymous PL/SQL block, you'd declare a variable whose datatype matches the one returned by that function (it is NUMBER), pass parameters and - that's it.
declare
result number;
begin
result := function_name(n_fdo => 1,
n_perc => 'ABC',
...
n_porto => 'XYZ');
end;
/

Not passing an OUT parameter in PL/SQL

So I have this interesting situation. I have a PL/SQL procedure where I pass two IN parameters and two OUT parameters:
PROCEDURE p_merge_catalog(p_merge_from_code VARCHAR2,
p_merge_to_code VARCHAR2,
msg_type_out OUT VARCHAR2,
msg_out OUT VARCHAR2)
IS
.
.
My conundrum is I'm using a job submission/scheduler program to call the procedure that does not seem to deal with OUT variables. I'm not able to bind variables to the OUT parameters; it only passes values. Is there a way to call this procedure without specifying an OUT parameter? Or maybe trick it and use some kind of hidden variable?
Not very beautiful for two outs, but working ;)
CREATE OR REPLACE FUNCTION f_merge_catalog_wrapper (
p_merge_from_code VARCHAR2,
p_merge_to_code VARCHAR2)
RETURN emp%ROWTYPE
IS
msg_type_out VARCHAR2(2000);
msg_out VARCHAR2(2000);
BEGIN
p_merge_catalog(p_merge_from_code, p_merge_to_code, msg_type_out, msg_out);
return msg_type_out || '#' || msg_out;
END;
Didn't check for typos. But the mechanic should be clear :o).
If you don't need the output:
CREATE OR REPLACE PROCEDURE p_merge_catalog_wrapper (
p_merge_from_code VARCHAR2,
p_merge_to_code VARCHAR2)
RETURN emp%ROWTYPE
IS
msg_type_out VARCHAR2(2000);
msg_out VARCHAR2(2000);
BEGIN
p_merge_catalog(p_merge_from_code, p_merge_to_code, msg_type_out, msg_out);
END;

New Oracle Package with Stored Procedure Including Parameters

I am having difficulty with writing my stored procedure within a package. Below is my stored procedure that compiles fine outside of the package, but I believe needs to be written differently within the package body. I admit this is my first time using a package...
create or replace PROCEDURE SP_COMMENT(P_MEMBER_ID IN VARCHAR2, P_MEMBER_LASTNAME IN
VARCHAR2, P_MEMBER_FIRSTNAME IN VARCHAR2, P_MEMBER_STARTDATE IN DATE,
P_MEMBER_ENDDATE IN DATE, P_PRODUCT_CAT_CODE IN VARCHAR2, P_COMMENT IN VARCHAR2,
COMMENT_CURSOR out sys_refcursor)
AUTHID CURRENT_USER
IS
BEGIN
EXECUTE IMMEDIATE
'INSERT INTO TEST
(
MEMBER_ID,
MEMBER_LASTNAME,
MEMBER_FIRSTNAME,
MEMBER_STARTDATE,
MEMBER_ENDDATE,
PRODUCT_CAT_CODE,
COMMENTS
)
VALUES
(
p_member_id,
p_member_lastname,
p_member_firstname,
p_member_startdate,
p_member_enddate,
p_product_cat_code,
p_comment)';
commit;
open COMMENT_CURSOR for select * from sconti.TEST;
END;
Below is the package that I started, and which is not working:
CREATE OR REPLACE
PACKAGE COMMENT_TEST IS
PROCEDURE SP_COMMENT(P_MEMBER_ID IN VARCHAR2, P_MEMBER_LASTNAME IN VARCHAR2,
P_MEMBER_FIRSTNAME IN VARCHAR2, P_MEMBER_STARTDATE IN DATE,
P_MEMBER_ENDDATE IN DATE, P_PRODUCT_CAT_CODE IN VARCHAR2, P_COMMENT IN VARCHAR2,
COMMENT_CURSOR out sys_refcursor) IS
BEGIN
EXECUTE IMMEDIATE
'INSERT INTO TEST
(
MEMBER_ID,
MEMBER_LASTNAME,
MEMBER_FIRSTNAME,
MEMBER_STARTDATE,
MEMBER_ENDDATE,
PRODUCT_CAT_CODE,
COMMENTS
)
VALUES
(
p_member_id,
p_member_lastname,
p_member_firstname,
p_member_startdate,
p_member_enddate,
p_product_cat_code,
p_comment)';
commit;
open COMMENT_CURSOR for select * from sconti.TEST;
END;
END COMMENT_TEST;
I look forward to any response to assist me....thanks!
I can't say for certain (because you haven't shared the error you're getting), but most basic error is a lack of understanding of the specification/body.
You've put the code into the package specification, rather than the body. The specification should just have the procedure declarations (i.e. no begin and end), where as the body has the full content of the procedure.
While it won't affect compilation, there is another problem: the SQL inside the string can't access the parameters supplied to the procedure. If you must use dynamic SQL (and there's absolutely no reason to in this case), then you need a using clause to bind the variable into the dynamic statement. In addition, making the SQL static will allow the SQL statement to be validated at compile-time, which has obvious advantages.
A revised packaged (specification and body) is below.
CREATE OR REPLACE PACKAGE comment_test IS
PROCEDURE sp_comment (p_member_id IN VARCHAR2,
p_member_lastname IN VARCHAR2,
p_member_firstname IN VARCHAR2,
p_member_startdate IN DATE,
p_member_enddate IN DATE,
p_product_cat_code IN VARCHAR2,
p_comment IN VARCHAR2,
comment_cursor OUT SYS_REFCURSOR);
END comment_test;
/
CREATE OR REPLACE PACKAGE BODY comment_test IS
PROCEDURE sp_comment (p_member_id IN VARCHAR2,
p_member_lastname IN VARCHAR2,
p_member_firstname IN VARCHAR2,
p_member_startdate IN DATE,
p_member_enddate IN DATE,
p_product_cat_code IN VARCHAR2,
p_comment IN VARCHAR2,
comment_cursor OUT SYS_REFCURSOR) IS
BEGIN
INSERT INTO test (member_id,
member_lastname,
member_firstname,
member_startdate,
member_enddate,
product_cat_code,
comments)
VALUES (p_member_id,
p_member_lastname,
p_member_firstname,
p_member_startdate,
p_member_enddate,
p_product_cat_code,
p_comment);
COMMIT;
OPEN comment_cursor FOR SELECT * FROM sconti.test;
END;
END comment_test;
/

Dynamic SQL accept table column as input in a procedure

Hey I am trying to write a procedure in which the user can insert which columns he would like to get as parameter input. As of right now when I run a test script I get this error:
error -1 message error in ct_cu_act_medrecon_pg.spm_search_patientmedrecs =>ORA-00933: SQL command not properly ended
The error is refering to the order by part in the select statement, and when I remove that I get an error saying:
error -1 message error in ct_cu_act_medrecon_pg.spm_search_patientmedrecs =>ORA-00904: "D"."P_INSERTDT_IN": invalid identifier
Here is the spec:
procedure spm_search_patientmedrecs (
p_columnsort_in in varchar2, --which is sort column
p_medmed_in in varchar2, --first column
p_planid_in in varchar2, --second column
p_detmed_in in varchar2, --third column
p_insertdt_in in varchar2, --fourth column
p_ascdesc_in in varchar2, --asc or desc in order by
p_return_cur_out out sys_refcursor,
p_err_code_out out number,
p_err_mesg_out out varchar2
);
Here is the procedure body:
procedure spm_search_patientmedrecs (
p_columnsort_in in varchar2,
p_medmed_in in varchar2,
p_planid_in in varchar2,
p_detmed_in in varchar2,
p_insertdt_in in varchar2,
p_ascdesc_in in varchar2,
p_return_cur_out out sys_refcursor,
p_err_code_out out number,
p_err_mesg_out out varchar2)
is
lv_sql varchar2(32767);
begin
lv_sql := '';
lv_sql := 'select h.p_medmed_in,
h.p_planid_in,
d.p_detmed_in,
d.p_insertdt_in
from membermedicalreconcilationhdr h,
membermedicalreconcilationdet d
where h.membermedreconciliationhdrskey =
d.membermedreconciliationhdrskey
order by h.p_columnsort_in p_ascdesc_in';
p_err_code_out := 0;
OPEN p_return_cur_out FOR lv_sql;
exception
when others then
p_err_code_out := -1;
p_err_mesg_out := 'error in ct_cu_act_medrecon_pg.spm_search_patientmedrecs =>'||sqlerrm;
end spm_search_patientmedrecs;
Here is my test script:
set serveroutput on
declare
type tempcursor is ref cursor;
v_cur_result tempcursor;
errcode number;
errmesg varchar2(1000);
begin
ct_cu_act_medrecon_pg.spm_search_patientmedrecs
('primarymemberplanid',
'membermedreconciliationhdrskey',
'primarymemberplanid',
'membermedreconciliationdetskey',
'inserteddt',
'ASC',
v_cur_result,
errcode,
errmesg
);
-- dbms_output.put_line(v_cur_result);
dbms_output.put_line('error '||errcode||' message '||errmesg);
end;
First off, I know how I'm handeling the error isnt the best way to do it but thats how the person asking me to do this wanted it.
Now I dont know if this is a possible thing to do in Oracle PL/SQL, but if it is I would greatly appreciate some help in pointing me in the right direction. If you guys need any more information feel free to ask and I will assist as best I can (Ive only been working with SQL and PL/SQL for 2 months). Thanks in advance.
Dynamic SQL means assembling strings which are executed as SQL statements. Your string hardcodes the parameter names, whereas what you actually need is the contents of the parameters.
Something like this:
lv_sql := 'select h.'||p_medmed_in||',
h.'||p_planid_in||',
d.'||p_detmed_in||',
d.'||p_insertdt_in||'
from membermedicalreconcilationhdr h,
membermedicalreconcilationdet d
where h.membermedreconciliationhdrskey =
d.membermedreconciliationhdrskey
order by h.'||p_columnsort_in||' '|| p_ascdesc_in;

Resources