I am running DBMS_OUTPUT.PUT_LINE to send a message from a procedure and I am trying to display the debug information of what a type variable contains BFILE
create or replace PROCEDURE P_FILEUPLOAD_XML IS
v_dir gzvcatg.gzvcatg_desc11%TYPE;
l_dir VARCHAR2(35);
l_fil VARCHAR2(30) := 'ES0000251446027471.xml';
l_loc BFILE;
BEGIN
l_loc := BFILENAME(v_dir,l_fil);
DBMS_OUTPUT.PUT_LINE(l_loc);
END;
At the moment of executing my procedure and waiting for a response from the log:
Anyone know why the error is due and how to correct it.
UPDATE:
Following the recommendation in the MT0 response making use of DBMS_LOB.READ, try the following:
create or replace PROCEDURE P_FILEUPLOAD_XML IS
v_dir gzvcatg.gzvcatg_desc11%TYPE;
l_dir VARCHAR2(35);
l_fil VARCHAR2(30) := 'ES0000251446027471.xml';
l_loc BFILE;
BEGIN
l_loc := BFILENAME(v_dir,l_fil);
DBMS_LOB.READ(l_loc IN BFILE);
END;
But executing it generates the following error:
Anyone know why the error is due
l_loc is a BFILE.
DBMS_OUTPUT.PUT_LINE( item IN VARCHAR2 ) takes a VARCHAR2 data type as its argument.
You cannot implicitly cast a BFILE to a VARCHAR2 so the procedure call raise an exception as it is the wrong type of argument to call the function with.
and how to correct it.
Read the file using DBMS_LOB.READ and use UTL_RAW.CAST_TO_VARCHAR2 to convert the RAW value you get from the LOB to a string so you can print it.
Related
I'm working on a PLSQL package that calls another PLSQL package that returns separated results (i.e OUT variables) as follows:
(1) SYS_REFCURSOR
(1) NUMBER
(1) VARCHAR2
This is the dbfiddle I build.
Full code of the linked dbfiddle:
/* Main table - it contains the data to use in a cursor: */
CREATE TABLE tpos_retbenf
(
id_serial NUMBER (9,0),
serial_nmb NUMBER(12,0)
);
/* Destination of the records detected on "tpos_retbenf": */
CREATE TABLE tbl_debug
(
msg_text VARCHAR2(1000),
record_date DATE
);
/* Add values to the main table: */
INSERT INTO tpos_retbenf (id_serial, serial_nmb)
VALUES (1, 202108311635);
/* Package that contains the code to execute: */
create or replace PACKAGE PCK_POS_UNO is
PROCEDURE SP_POS_UNO (ID_RECORD IN NUMBER,
CUR_RET_BENF OUT SYS_REFCURSOR,
IDERROR OUT NUMBER,
DSERROR OUT VARCHAR2);
end PCK_POS_UNO;
/
create or replace PACKAGE BODY PCK_POS_UNO is
/* This is the procedure that returns results in separated variables: */
PROCEDURE SP_POS_UNO (ID_RECORD IN NUMBER,
CUR_RET_BENF OUT SYS_REFCURSOR,
IDERROR OUT NUMBER,
DSERROR OUT VARCHAR2) AS
v_temp number(6) := 0;
v_S varchar2(1) := 'S';
BEGIN
if ID_RECORD is null or ID_RECORD <= 0 then
IDERROR := -1;
DSERROR := 'Id no valido para la operacion';
goto finalizar;
end if;
select count(1) into v_temp
from tpos_retbenf r
where r.id_serial = ID_RECORD;
if v_temp = 0 then
IDERROR := -1;
DSERROR := 'Id no encontrado';
goto finalizar;
end if;
OPEN CUR_RET_BENF FOR
select r.id_serial, r.serial_nmb
from tpos_retbenf r
where r.id_serial = ID_RECORD;
<<finalizar>>
null;
END SP_POS_UNO;
END PCK_POS_UNO;
/
/* Package that calls the "SP_POS_UNO" procedure from the "PCK_POS_UNO" package: */
create or replace PACKAGE PKG_BH_ONLINE_INFORMATION IS
PROCEDURE ONLINENOVELTYBEN
(
V_NID_DEV IN NUMBER,
CV_1 IN OUT SYS_REFCURSOR
);
END PKG_BH_ONLINE_INFORMATION;
/
create or replace PACKAGE BODY PKG_BH_ONLINE_INFORMATION IS
PROCEDURE ONLINENOVELTYBEN
(
V_NID_DEV IN NUMBER,
CV_1 IN OUT SYS_REFCURSOR
) IS
V_USER VARCHAR2(10 CHAR) := 'INTERNET';
V_QUERY VARCHAR2(10000 CHAR);
-- Variables:
V_OUT_CUR_RET_BENF SYS_REFCURSOR;
V_OUT_IDERROR NUMBER;
V_OUT_DSERROR VARCHAR2(10000 CHAR);
BEGIN
/*
Here, the "PCK_POS_UNO.SP_POS_UNO" is called
from "PKG_BH_ONLINE_INFORMATION" as follows:
*/
V_QUERY := 'SELECT APPLICATION_POS.PCK_POS_UNO.SP_POS_UNO(:V_NID_DEV, :V_OUT_CUR_RET_BENF, :V_OUT_IDERROR, :V_OUT_DSERROR) FROM DUAL';
EXECUTE IMMEDIATE V_QUERY INTO V_OUT_CUR_RET_BENF, V_OUT_IDERROR, V_OUT_DSERROR USING V_NID_DEV, V_OUT_CUR_RET_BENF, V_OUT_IDERROR, V_OUT_DSERROR ;
/*
An this error occurs:
Error: ORA-00904: "PCK_POS_UNO"."SP_POS_UNO": invalid identifier - StackTrace: ORA-06512: in line 24
*/
-- After getting the results in (V_OUT_CUR_RET_BENF, V_OUT_IDERROR, V_OUT_DSERROR) variables,
-- a LOOP is executed for retrieve the records in "V_OUT_CUR_RET_BENF" cursor...
-- It doesn't continue here due to error shown above.
END ONLINENOVELTYBEN;
END PKG_BH_ONLINE_INFORMATION;
/
When the following code is going to be executed:
V_QUERY := 'SELECT APPLICATION_POS.PCK_POS_UNO.SP_POS_UNO(:V_NID_DEV, :V_OUT_CUR_RET_BENF, :V_OUT_IDERROR, :V_OUT_DSERROR) FROM DUAL';
EXECUTE IMMEDIATE V_QUERY INTO V_OUT_CUR_RET_BENF, V_OUT_IDERROR, V_OUT_DSERROR USING V_NID_DEV, V_OUT_CUR_RET_BENF, V_OUT_IDERROR, V_OUT_DSERROR ;
The error says:
Error: ORA-00904: "APPLICATION_POS"."PCK_POS_UNO"."SP_POS_UNO": invalid identifier -
StackTrace: ORA-06512: in line 24
I've tried so far:
Search for ORA-00904 error - in this answer says "proper permissions on objects involved in the query" - which I share, but, I don't know how to argument this option (since I can do a simple SELECT to that table and the results are shwon, hence, they might not accept this argument). Related to this argument, I can't get listed the PCK_POS_UNO package "since the OWNER is different from the one I'm usually using (that is APPLICATION)".
I made a copy of this package/procedure and was able to execute the procedure/package via SQL Developer - see screenshot, but, the same error ORA-00904 occurs.
Screentshot of the execution of the package:
Results:
Change the code that calls the procedure that has OUT parameters, but, I'm unable to get a successful combination that allows the compilation and execution of the code as a whole.
Examples - all based on internet searchs and my own "instinct":
(1): Added (;) at the end of the dynamic-sql string:
V_QUERY := 'SELECT APPLICATION_POS.PCK_POS_UNO.SP_POS_UNO((:V_NID_DEV, :V_OUT_CUR_RET_BENF, :V_OUT_IDERROR, :V_OUT_DSERROR) FROM DUAL;';
(2): Removing the OWNER - in this case "APPLICATION_POS":
V_QUERY := 'SELECT PCK_POS_UNO.SP_POS_UNO(:V_NID_DEV, :V_OUT_CUR_RET_BENF, :V_OUT_IDERROR, :V_OUT_DSERROR) FROM DUAL';
(3): Calling the procedure directly - it shows SP2-0552: bind variable "V_NID_DEV" not declared - but, how?, in a separated sample, the variable "V_NID_DEV" is declared and with value "2462013":
PCK_POS_UNO.SP_POS_UNO(:V_NID_DEV, :V_OUT_CUR_RET_BENF, :V_OUT_IDERROR, :V_OUT_DSERROR);
(4): Calling the procedure directly (removing also the points) - in this case, ORA-01001 - invalid cursor error is generated - which I think it doesn't make sense - since the OUT cursor is not being opened for read or operated somehow.
PCK_POS_UNO.SP_POS_UNO(V_NID_DEV, V_OUT_CUR_RET_BENF, V_OUT_IDERROR, V_OUT_DSERROR);
I'm really run out of ideas - since I'm not familiar with this type of creating packages and passing values between packages and I didn't created this code.
Is there any way to make this code work?
Package modified to call procedure SP_POS_UNO:
CREATE OR REPLACE PACKAGE BODY PKG_BH_ONLINE_INFORMATION
IS
PROCEDURE ONLINENOVELTYBEN(V_NID_DEV IN NUMBER,
CV_1 IN OUT SYS_REFCURSOR
)
IS
V_USER VARCHAR2(10 CHAR) := 'INTERNET';
V_QUERY VARCHAR2(10000 CHAR);
-- Variables:
V_OUT_CUR_RET_BENF SYS_REFCURSOR;
V_OUT_IDERROR NUMBER;
V_OUT_DSERROR VARCHAR2(10000 CHAR);
BEGIN
/*
Here, the "PCK_POS_UNO.SP_POS_UNO" is called
from "PKG_BH_ONLINE_INFORMATION" as follows:
*/
V_QUERY:='Begin
PCK_POS_UNO.SP_POS_UNO(:V_NID_DEV, :V_OUT_CUR_RET_BENF, :V_OUT_IDERROR, :V_OUT_DSERROR);
End;';
--
EXECUTE IMMEDIATE V_QUERY
USING V_NID_DEV,
out V_OUT_CUR_RET_BENF,
out V_OUT_IDERROR,
out V_OUT_DSERROR ;
Dbms_Output.Put_Line('V_OUT_IDERROR='||V_OUT_IDERROR);
Dbms_Output.Put_Line('V_OUT_DSERROR='||V_OUT_DSERROR);
--
CV_1:=V_OUT_CUR_RET_BENF;
END ONLINENOVELTYBEN;
--
END PKG_BH_ONLINE_INFORMATION;
I am concatenating string using cursor (to form query to execute later). Here, the query that will be formed is going to be way bigger that what VARCHAR2(32767) can handle. There fore, I am getting error on proc execution - ORA-06502: PL/SQL: numeric or value error: character string buffer too small.
I used CLOB data type as well bu got error ORA-06502: PL/SQL: numeric or value error.
My code is here below:
CREATE OR REPLACE PROCEDURE sp_Market
IS
Names VARCHAR2(32767);
BEGIN
DECLARE CURSOR cur IS ('Select ID, Order_of, field_name
FROM pld_medicare_config');
BEGIN
FOR i IN cur
LOOP
Names := Names || i.sqql;
END LOOP;
dbms_output.put_line(Names);
END;
END sp_Market;
How can I handle my string of queries and what data type is there to accomplish the task?
CLOB is OK (as far as I can tell); I doubt queries you store in there are that big.
Remove dbms_output.put_line call from the procedure; I suspect it is the one that raises the error.
I'm not sure how you got any runtime error, as your procedure won't compile.
The valid PL/SQL version would look something like this:
create or replace procedure sp_market is
names varchar2(32767);
begin
for r in (
select id, order_of, field_name
from pld_medicare_config
)
loop
names := names || ' ' || r.field_name;
end loop;
names := ltrim(names);
dbms_output.put_line(names);
end sp_market;
If names needs to be longer, change the datatype to clob.
Use the CLOB datatype and append data using the dbms_lob.writeappend procedure. This is the reference (Oracle 18c).
The error probably origins with the dbms_output.put_line call. The procedure is defined for varchar2 arguments only which means that an implicit conversion takes place during the call. It will fail for clob contents longer than 32767 chars/bytes.
Alternatively you may declare a collection over varchar2(4000) and fill the collection elements sequentially:
CREATE OR REPLACE PROCEDURE sp_Market
IS
TYPE tLongString IS TABLE OF VARCHAR2(4000) INDEX BY BINARY_INTEGER;
cNames tLongString;
BEGIN
DECLARE CURSOR cur IS Select ID, Order_of, field_name, sqql FROM pld_medicare_config;
BEGIN
FOR i IN cur
LOOP
cNames(cNames.COUNT+1) := i.sqql;
END LOOP;
END;
END sp_Market;
Note
Rectified code, will compile now.
the below oracel procedure keeps showing me "pls-00103 encountered the symbol create" and i am not ablt to figure out why.. please help
create or replace procedure myproc
(
otherdate in varchar2
)
as
mystringdate varchar2(20);
begin
create or replace function checkdate(givdate in varchar2) return number
as
givedate1 date;
begin
givedate1 := todate(givdate);
return1;
exception
when others then
return 0;
end;
mystringdate := ltrim(rtrim(otherdate));
if checkdate(mystringdate,'dd-mm-yyyy')= 1 then
DBMS_OUTPUT.PUT_LINE('it is a date format');
else
DBMS_OUTPUT.PUT_LINE('it is not a date format');
endif
end myproc;
i tried more like \ symbol and all but not working. please help
This is weird, you started creating a proc and then inside begin you started creating function, you need to remove create function from there. Why you want to do that?
Remove this:
create or replace function checkdate(givdate in varchar2) return number
as
givedate1 date;
begin
givedate1 := todate(givdate);
return1;
exception
when others then
return 0;
end;
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;
Can PL/SQL procedure in Oracle know it's own name?
Let me explain:
CREATE OR REPLACE procedure some_procedure is
v_procedure_name varchar2(32);
begin
v_procedure_name := %%something%%;
end;
After %%something%% executes, variable v_procedure_name should contain 'SOME_PROCEDURE'. It is also OK if it contains object_id of that procedure, so I can look up name in all_objects.
Try:
v_procedure_name := $$PLSQL_UNIT;
There's also $$PLSQL_LINE if you want to know which line number you are on.
If you are pre-10g, you can 'dig' (parse) it out of
dbms_utility.format_call_stack
Procedures/functions in packages can be overloaded (and nested), so the package name/line number is normally better than the name.
In 10g and 11g I use the "owa_util.get_procedure" function. I normally use this in packages as it will also return the name of an internal procedure or function as part of the package name, i.e. (package_name).(procedure name). I use this to provide a generic EXCEPTION template for identifying where an exception occured.
CREATE OR REPLACE procedure some_procedure is
v_procedure_name varchar2(32);
begin
v_procedure_name := owa_util.get_procedure;
end;
CREATE OR REPLACE PACKAGE some_package
AS
FUNCTION v_function_name
RETURN DATE;
END;
/
CREATE OR REPLACE PACKAGE BODY some_package
AS
FUNCTION v_function_name
RETURN DATE
IS
BEGIN
RETURN SYSDATE;
EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE('ERROR IN '||owa_util.get_procedure);
DBMS_OUTPUT.PUT_LINE(SQLERRM);
END;
END;
/
Here's a neat function that takes advantage of REGEXP_SUBSTR.
I've tested it in a package (and it even works if another procedure in the package calls it):
FUNCTION SET_PROC RETURN VARCHAR2 IS
BEGIN
RETURN NVL(REGEXP_SUBSTR(DBMS_UTILITY.FORMAT_CALL_STACK,
'procedure.+\.(.+)\s', 1,1,'i',1), 'UNDEFINED');
END SET_PROC;