Please help in finding the error while creating the package with overloading functions.
Error shown:
PL-00103: Encountered the symbol "NUMOU"when expecting one of the following: language.
PL-00103: Encountered the symbol "Function" when expecting one of the following: end not pragma final instantiable order overriding static member constructor map.
code:
create or replace package over_load as
function print_it(numin varchar2) return number is numou number;
begin
numou := to_number(numin, '999,999.00');
dbms_output.put_line(numou);
return numou;
exception
when others then
dbms_output.put_line('Wrong string format');
return numou;
end;
function print_it(datin date) return varchar2 is datout varchar2(30);
dumcha varchar2(30);
dumdat date;
begin
dumcha := to_char(datin);
dumdat := to_date(dumcha,'FXDD-MON-YYYY');
datout := to_char(datin, 'fmMOn, DD YYYY');
dbms_output.put_line(datout);
return datout;
Exception
when others then
dbms_output.put_line('Wrong input date format');
return '0';
end;
end;
In Oracle RDBMS You MUST specify package (for public methods) and package body containing implementation for all public methods and optionally You can add some private methods.
Package specification:
create or replace package over_load as
function print_it(numin varchar2) return number;
function print_it(datin date) return varchar2;
end;
And body:
create or replace package body over_load as
function print_it(numin varchar2) return number is
numou number;
begin
numou := to_number(numin, '999,999.00');
dbms_output.put_line(numou);
return numou;
exception
when others then
dbms_output.put_line('Wrong string format');
return numou;
end;
function print_it(datin date) return varchar2 is
datout varchar2(30);
dumcha varchar2(30);
dumdat date;
begin
dumcha := to_char(datin);
dumdat := to_date(dumcha,'FXDD-MON-YYYY');
datout := to_char(datin, 'fmMOn, DD YYYY');
dbms_output.put_line(datout);
return datout;
exception
when others then
dbms_output.put_line('Wrong input date format');
return '0';
end;
end;
NOTE THAT:
To enable output from DBMS_OUTPUT in SQL*Plus You must enable serveroutput:
SQL> set serveroutput on size 30000;
Related
In the package I have couple of procedure that set global variables, example below:
...
PROCEDURE setA (pp IN VARCHAR2)
IS BEGIN global_vName := pp; END;
PROCEDURE setB (qq IN VARCHAR2)
IS BEGIN global_vColor := qq; END;
FUNCTION getA RETURN VARCHAR2
IS BEGIN RETURN global_vName; END;
FUNCTION getB RETURN VARCHAR2
IS BEGIN RETURN global_vColor; END;
...
Now in the PL/SQL block I'm doing test if they are working correclty:
Begin
mypack.setA('NameA');
mypack.setB('ColorB');
End;
How to write a procedure that will check if global_vName and global_vColor are set up?
If they are null procedure should return exception. Please help.
Do you mean this?
FUNCTION getA RETURN VARCHAR2 IS
BEGIN
IF global_vName IS NULL THEN
RAISE NO_DATA_FOUND;
END IF;
RETURN global_vName;
END;
There is no possibility to execute some code after the end statement - you should write it explicitly if you need additional check. As I understand, you want be sure that global variables are always initialized, so you can use the package initialization:
create or replace package body mypack as
PROCEDURE setA (pp IN VARCHAR2)
IS BEGIN global_vName := pp; END;
PROCEDURE setB (qq IN VARCHAR2)
IS BEGIN global_vColor := qq; END;
FUNCTION getA RETURN VARCHAR2
IS BEGIN RETURN global_vName; END;
FUNCTION getB RETURN VARCHAR2
IS BEGIN RETURN global_vColor; END;
< here are your other functions and procedures >
begin
-- here is an initialization section
setA('NameA');
setB('ColorB');
end mypack;
The initialization section will be executed automatically by Oracle before the first user's call to package (function, procedure, cursor, variable, etc.). So you can be sure that your variables are always initialized.
I noticed that TO_TIMESTAMP raises a variety of error codes depending on how it failed;
--01847
select to_timestamp('2016-01-0a', 'yyyy-MM-dd') from dual;
--01858
select to_timestamp('2016-01-aa', 'yyyy-MM-dd') from dual;
--01843
select to_timestamp('2016-15-01', 'yyyy-MM-dd') from dual;
Given that it doesn't raise a single error code, how can I catch the error without resorting to using the catch-all OTHERS:
DECLARE
foo timestamp;
BEGIN
select to_timestamp('2016-01-0a', 'yyyy-MM-dd') into foo from dual;
EXCEPTION
WHEN OTHERS THEN
dbms_output.put_line('bad date');
END;
If you are on 12cR2, then you can use VALIDATE_CONVERSION to check the validity of a potential type conversion before making the conversion and avoid the exception entirely.
In earlier versions, you could create your own equivalent function for TIMESTAMPs that attempts the conversion and handles the exceptions. You could declare each exception-type of interest individually and log/handle the failure-modes of interest separately for each as needed, with an overall WHEN OTHERS for the stuff you don't care about or want to log/handle:
CREATE OR REPLACE FUNCTION IS_TIMESTAMP_FORMAT_OK(P_TIMESTAMP_TEXT IN VARCHAR2, P_FORMAT IN VARCHAR2 DEFAULT 'yyyy-MM-dd')
RETURN BOOLEAN
IS
--exception names
V_TIMESTAMP TIMESTAMP;
DAY_OF_MONTH EXCEPTION;
NON_NUMERIC EXCEPTION;
--etc.
PRAGMA EXCEPTION_INIT (DAY_OF_MONTH, -1847);
PRAGMA EXCEPTION_INIT (NON_NUMERIC, -1858);
BEGIN
V_TIMESTAMP := to_timestamp(P_TIMESTAMP_TEXT, P_FORMAT);
RETURN TRUE;
EXCEPTION WHEN DAY_OF_MONTH
THEN
DBMS_OUTPUT.PUT_LINE('The day of month must be between...');
RETURN FALSE;
WHEN NON_NUMERIC
THEN
DBMS_OUTPUT.PUT_LINE('Non-Numeric data was found...');
RETURN FALSE;
--etc.
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE(UTL_LMS.FORMAT_MESSAGE('Unexpected timestamp problem: %s', SQLERRM));
RETURN FALSE;
END;
/
Then you can log/handle the types of interest:
DECLARE
V_CHECK BOOLEAN;
BEGIN
V_CHECK := IS_TIMESTAMP_FORMAT_OK('2016010a');
V_CHECK := IS_TIMESTAMP_FORMAT_OK('2016-01-aa');
V_CHECK := IS_TIMESTAMP_FORMAT_OK('2016-01-0a');
IF IS_TIMESTAMP_FORMAT_OK('2014-01-01')
THEN
DBMS_OUTPUT.PUT_LINE('It is ok. Yay');
END IF;
END;
/
Unexpected timestamp problem: ORA-01862: the numeric value does not match the
length of the format item
Non-Numeric data was found...
The day of month must be between...
It is ok. Yay
Or if you don't care about logging/handle different failure modes and just want to prevent broad exception-catching, you can go ahead and use WHEN OTHERS, but in isolated scope:
CREATE OR REPLACE FUNCTION
IS_TIMESTAMP_FORMAT_OK(P_TIMESTAMP_TEXT IN VARCHAR2, P_FORMAT IN VARCHAR2 DEFAULT 'yyyy-MM-dd')
RETURN BOOLEAN
IS
V_TIMESTAMP TIMESTAMP;
BEGIN
V_TIMESTAMP := to_timestamp(P_TIMESTAMP_TEXT, P_FORMAT);
RETURN TRUE;
EXCEPTION WHEN OTHERS THEN
RETURN FALSE;
END;
/
Or Inline:
DECLARE
V_MY_TIMESTAMP TIMESTAMP;
BEGIN
-- some other code ...
BEGIN
V_MY_TIMESTAMP := to_timestamp('2016-01-aa', 'yyyy-MM-dd');
EXCEPTION WHEN OTHERS THEN NULL;
END;
DBMS_OUTPUT.PUT_LINE('My Timestamp:'||V_MY_TIMESTAMP);
END;
/
My Timestamp:
I am trying to make a simple call to a function(Test2) which takes a cursor, and returns a cursor.
I am stuck with the error:
Error(23,17): PLS-00306: wrong number or types of arguments in call to 'TEST2'
What is wrong with my function call?
v_resp := TEST2(v_req);
Here is my test:
CREATE OR REPLACE TYPE TRANS_OBJ AS OBJECT (TRANSNO CHAR(8));
CREATE OR REPLACE TYPE TRANS_OBJ_TAB AS TABLE OF TRANS_OBJ;
CREATE OR REPLACE FUNCTION TEST2 (v_rc IN SYS_REFCURSOR) RETURN TRANS_OBJ_TAB
IS
v_resp TRANS_OBJ_TAB := TRANS_OBJ_TAB();
BEGIN
v_resp.extend;
v_resp(1) := TRANS_OBJ('222222');
RETURN v_resp;
END;
CREATE OR REPLACE FUNCTION TEST1 RETURN TRANS_OBJ_TAB
IS
TRANSNO CHAR(8);
v_cnt number := 0;
v_req TRANS_OBJ_TAB := TRANS_OBJ_TAB();
v_resp TRANS_OBJ_TAB := TRANS_OBJ_TAB();
--v_resp sys_refcursor;
CURSOR v_rc IS SELECT '1111' AS TRANSNO FROM DUAL;
BEGIN
OPEN v_rc;
LOOP
fetch v_rc into TRANSNO;
EXIT WHEN v_rc%NOTFOUND;
v_req.extend;
v_cnt := v_cnt + 1;
v_req(v_cnt) := TRANS_OBJ(TRANSNO);
END LOOP;
CLOSE v_rc;
v_resp := TEST2(v_req);
RETURN v_resp;
END;
/
DROP TYPE TRANS_OBJ_TAB;
DROP TYPE TRANS_OBJ;
DROP FUNCTION TEST1;
DROP FUNCTION TEST2;
First you are not returning a CURSOR from TEST2 function as you says (try return sys_refcursor).
On the other hand v_req is not an sys_refcursor, besides v_resp can't contains a cursor too. Review the types you are using.
Hope this help!!!
I have the following code
CREATE OR REPLACE FUNCTION slow_function (p_in IN NUMBER)
RETURN NUMBER
AS
BEGIN
DBMS_LOCK.sleep(1);
RETURN p_in;
END;
/
CREATE OR REPLACE PACKAGE cached_lookup_api AS
FUNCTION get_cached_value (p_id IN NUMBER)
RETURN NUMBER;
PROCEDURE clear_cache;
END cached_lookup_api;
/
CREATE OR REPLACE PACKAGE BODY cached_lookup_api AS
TYPE t_tab IS TABLE OF NUMBER
INDEX BY BINARY_INTEGER;
g_tab t_tab;
g_last_use DATE := SYSDATE;
g_max_cache_age NUMBER := 10/(24*60); -- 10 minutes
-- -----------------------------------------------------------------
FUNCTION get_cached_value (p_id IN NUMBER)
RETURN NUMBER AS
l_value NUMBER;
BEGIN
IF (SYSDATE - g_last_use) > g_max_cache_age THEN
-- Older than 10 minutes. Delete cache.
g_last_use := SYSDATE;
clear_cache;
END IF;
BEGIN
l_value := g_tab(p_id);
EXCEPTION
WHEN NO_DATA_FOUND THEN
-- Call function and cache data.
l_value := slow_function(p_id);
g_tab(p_id) := l_value;
END;
RETURN l_value;
END get_cached_value;
-- -----------------------------------------------------------------
-- -----------------------------------------------------------------
PROCEDURE clear_cache AS
BEGIN
g_tab.delete;
END;
-- -----------------------------------------------------------------
END cached_lookup_api;
/
I want to pass two parameters "pi_value1" and "pi_value2" both of varchar2 to the function slow_function instead of "p_in". Is is possible to cache the results with two in parameters in oracle 10g .
the above code works fine with 1 parameter.
Please any one explain?
You'd need to create a two-dimensional array type to cache the values. Something along the lines of this (omitting the cache expiration code since that isn't changing)
CREATE OR REPLACE PACKAGE BODY cached_lookup_api
AS
TYPE t_pi_value2_tbl IS TABLE OF NUMBER
INDEX BY VARCHAR2(100);
TYPE t_cache IS TABLE OF t_pi_value2_tbl
INDEX BY VARCHAR2(100);
g_cache t_cache;
FUNCTION get_cached_value( p_pi_value1 IN VARCHAR2,
p_pi_value2 IN VARCHAR2 )
IS
BEGIN
RETURN g_cache(p_pi_value1)(p_pi_value2);
EXCEPTION
WHEN no_data_found
THEN
g_cache(p_pi_value1)(p_pi_value2) := slow_function( p_pi_value1, p_pi_value2 );
RETURN g_cache(p_pi_value1)(p_pi_value2);
END;
END;
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;