Given Date valid in Oracle [duplicate] - sql

This question already has answers here:
PL/SQL check date is valid
(2 answers)
Given Date valid [closed]
Closed 9 years ago.
I want to verify valid date for all the formats
I am getting this error.
My input is IDateFormat = 'MM/YY/DD' and IStringDate = '2001-01-01'
I am getting the below error.
ORA-01843: not a valid month
ORA-06512: at "NECHO_APP.CONVERTTODATE" ORA-06512: at line 10 2011-01-01 Process exited.
CREATE OR REPLACE PROCEDURE convertToDate
(IDateFormat Varchar2,
IStringDate Varchar2,
OConvertedDate out timestamp,
OError OUT Int )
AS
TDateFormat Varchar2(20);
TStringDate Varchar2(20);
BEGIN
OError := 0;
TDateFormat := LTrim(RTrim(IDateFormat));
TStringDate := LTrim(RTrim(IStringDate));
DBMS_OUTPUT.PUT_LINE(TStringDate);
IF IS_VALID(TStringDate,'yyyy-mm-dd') = 1 THEN
SELECT TO_DATE(TStringDate,TDateFormat) INTO OConvertedDate FROM DUAL;
OError := 0;
END IF;
END;
- FUNCTION:
create or replace function is_valid(p_val in varchar2, fmt varchar2)
return number
is
not_a_valid_day exception;
not_a_valid_month exception;
pragma exception_init(not_a_valid_day, -1847);
pragma exception_init(not_a_valid_month, -1843);
l_date date;
begin
l_date := to_date(p_val, fmt);
return 1;
exception
when not_a_valid_day or not_a_valid_month
then return 0;
end is_valid;

You should use this
SELECT TO_CHAR(TO_DATE(TStringDate,'YYYY-MM-DD'),TDateFormat) INTO OConvertedDate FROM DUAL;
However, you should go through the usage of to_date and to_char.

Related

Error in return of PLSQL ORACLE Not Working

This Code is:
CREATE OR REPLACE
PROCEDURE Actualiza_Saldo(fecha_ini IN DATE, fecha_fin IN DATE) RETURN NUMBER
AS
fechaTemp DATE;
diasTotales NUMBER := fecha_fin- fecha_ini;diasLaborables NUMBER;
sab VARCHAR2(10) := 'SÁBADO';dom VARCHAR2(10) := 'DOMINGO';diasTemp VARCHAR2(10);
BEGIN
diasLaborables:= diastotales;
FOR i IN 0..diasTotales LOOP
fechaTemp := fecha_ini + i;
DBMS_OUTPUT.PUT_LINE(to_char(fechaTemp));
diasTemp := TO_CHAR(fechaTemp, 'DAY', 'NLS_DATE_LANGUAGE=SPANISH');
IF (TRIM(diasTemp)=sab or TRIM(diasTemp)=dom) THEN
diaslaborables := diaslaborables-1;
END IF;
END LOOP;
dbms_output.put_line(diaslaborables);
RETURN diasLaborables;
END Actualiza_Saldo;
If I execute without returning it works, if I try to return a value it fails, I do not know what could be happening.
The error of oracle is:
Warning: la ejecución ha terminado con advertencias
PROCEDURE Actualiza_Saldo(fecha_ini Compilado.
Error que empieza en la línea 1 del comando:
EXEC Actualiza_Saldo();
Informe de error:
ORA-06550: línea 1, columna 7:
PLS-00905: el objeto HR.ACTUALIZA_SALDO no es válido
ORA-06550: línea 1, columna 7:
PL/SQL: Statement ignored
06550. 00000 - "line %s, column %s:\n%s"
*Cause: Usually a PL/SQL compilation error.
*Action:
The code with constant value:
CREATE OR REPLACE
PROCEDURE Actualiza_Saldo(fecha_ini IN DATE DEFAULT '10/08/2018', fecha_fin IN DATE DEFAULT '30/08/2018')
AS
fechaTemp DATE;
diasTotales NUMBER := fecha_fin- fecha_ini;diasLaborables NUMBER;
sab VARCHAR2(10) := 'SÁBADO';dom VARCHAR2(10) := 'DOMINGO';diasTemp VARCHAR2(10);
BEGIN
diasLaborables:= diastotales;
FOR i IN 0..diasTotales LOOP
fechaTemp := fecha_ini + i;
DBMS_OUTPUT.PUT_LINE(to_char(fechaTemp));
diasTemp := TO_CHAR(fechaTemp, 'DAY', 'NLS_DATE_LANGUAGE=SPANISH');
IF (TRIM(diasTemp)=sab or TRIM(diasTemp)=dom) THEN
diaslaborables := diaslaborables-1;
END IF;
END LOOP;
dbms_output.put_line(diaslaborables);
END Actualiza_Saldo;
EXEC Actualiza_Saldo();
And the exit of the code without the returns and the test values ​​is a route from the start date and the final date subtracting the days Saturday and Sunday.
PROCEDURE Actualiza_Saldo(fecha_ini Compilado.
anonymous block completed
10/08/18
11/08/18
12/08/18
13/08/18
14/08/18
15/08/18
16/08/18
17/08/18
18/08/18
19/08/18
20/08/18
21/08/18
22/08/18
23/08/18
24/08/18
25/08/18
26/08/18
27/08/18
28/08/18
29/08/18
30/08/18
14
But if I try to return the value the algorithm dies.
I have no idea what I am doing wrong or where is the fault, if you could help me I would greatly appreciate it.
Procedures cannot return a value, in Oracle, You can have out-parameters which would be visible after the procedure runs.
But here is another option you can try, instead of writing code to generate dates between two, try to do it using a single select query and open a out cursor to have the values populated after the proc completes
An example as follows
create or replace procedure generate_dates(start_date in date, end_date in date, result_set out sys_refcursor)
as
begin
open result_set for
select trunc(start_date)+level as output_dates
from dual
connect by level<=trunc(end_date)-trunc(start_date);
end;
if you are using sqlplus to connect to your database
you would call the proc as follows
var x refcursor
begin
generate_dates(date '2018-01-01',date '2018-12-31',:x);
end;
print x;
My mistake was that I was not doing a function but a procedure solved.
CREATE OR REPLACE
FUNCTION HR.Actualiza_Saldo(fecha_ini IN DATE/* DEFAULT '10/08/2018'*/, fecha_fin IN DATE/* DEFAULT '30/08/2018'*/) RETURN NUMBER
AS

Invalid Identifier When Trying to Use Package Function in Summation Expression

I'm trying to use the sum function with a package function but running into an "invalid identifier" bug. Here's some example code with the error causing function commented
create or replace type numType as object
(
myNum number
)
;
/
create or replace type numTypes is table of numType;
/
create or replace package testNumberPackage as
function ReturnNum(in_numType numType) return number;
end;
/
create or replace package body testNumberPackage as
function ReturnNum(in_numType numType) return number is
begin
return in_numType.myNum;
end;
end;
/
declare l_numTypes numTypes;
l_count number;
begin
l_numTypes := numTypes();
for i in 1 .. 100 loop
l_numTypes.extend(1);
l_numTypes(l_numTypes.last) := numType(i);
end loop;
select sum(n.myNum) into l_count from table(l_numTypes) n;
select sum(testNumberPackage.ReturnNum(n)) into l_count from table(l_numTypes) n; --causes the error
dbms_output.put_line(l_count);
end;
/
The exact error for this code is
ORA-06550: line 11, column 42
PL/SQL: ORA-00904: "N": invalid identifier
ORA-6550: line 11, column 3:
PL/SQL: SQL Statement ignored
Thanks for any help.
The first issue is that you can't pass a table into a parameter by using its alias. It doesn't even make sense to try doing that.
The next issue is how to get the column mynum that is returned from the table(l_numTypes) into the correct format to pass into testNumberPackage.ReturnNum, since it's of NUMBER datatype, and the function is expecting a numtype parameter.
To do that, you need to pass in an object with that column, like so: numtype(n.mynum).
The following works for me:
declare
l_numTypes numTypes;
l_count number;
begin
l_numTypes := numTypes();
for i in 1 .. 100 loop
l_numTypes.extend(1);
l_numTypes(l_numTypes.last) := numType(i);
end loop;
select sum(n.myNum) into l_count from table(l_numTypes) n;
select sum(testNumberPackage.ReturnNum(numtype(n.mynum))) into l_count from table(l_numTypes) n; --causes the error
dbms_output.put_line(l_count);
end;
/
5050
Clear as mud?

PL SQL : custom data type declaration of the type of this expression is incomplete or malformed function

I have create a package with a function like this :
create or replace
PACKAGE TRANSAC_ERRONNEES AS
TYPE dateArrayVar IS TABLE OF DATE;
FUNCTION calc_date_moyenne(dateArrayIn dateArrayVar
) RETURN DATE;
END TRANSAC_ERRONNEES;
Body :
CREATE OR REPLACE PACKAGE BODY TRANSAC_ERRONNEES AS
FUNCTION calc_date_moyenne(dateArrayIn datearrayvar) RETURN DATE IS
dateFinal DATE;
tempsEnSeconde NUMBER;
tempsMoyenEnSeconde NUMBER;
BEGIN
tempsEnSeconde := 0;
tempsMoyenEnSeconde := 0;
FOR i IN 1..dateArrayIn.count loop
tempsEnSeconde := to_number(to_char(dateArrayIn(i), 'HH24')) * 60 * 60 + to_number(to_char(dateArrayIn(i), 'MI')) * 60 + to_number(to_char(dateArrayIn(i), 'SS'));
tempsMoyenEnSeconde := tempsMoyenEnSeconde+tempsEnSeconde;
end loop;
tempsMoyenEnSeconde := tempsMoyenEnSeconde/dateArrayIn.count;
dateFinal := to_date(TO_CHAR(dateArrayIn(1),'DD-MM-YYYY') || ' ' || TO_CHAR(to_date(tempsMoyenEnSeconde,'sssss'), 'HH24:MI:SS'), 'DD-MM-YYYY HH24:MI:SS');
dbms_output.put_line(TO_CHAR(dateFinal,'DD-MM-YYYY HH24:MI:SS'));
RETURN dateFinal;
END calc_date_moyenne;
END TRANSAC_ERRONNEES;
/
I try to test this function like this :
DECLARE
dates dateArrayVar;
resultat DATE;
BEGIN
dates := dateArrayVar(SYSDATE, SYSDATE);
resultat := transac_erronnees.calc_date_moyenne(dates);
END;
I'm getting this following error :
PLS-00320: the declaration of the type of this expression is
incomplete or malformed
Please let me know the error. Thanks in advance.
You are using it in incorrect way. You need to use array with extend to assign memory and then assign value in it.
DECLARE
dates dateArrayVar;
resultat DATE;
BEGIN
dates.extend(2); -- Since you want to assign two values, extend by 2
dates(1) := SYSDATE;
dates(2) := SYSDATE;
resultat := transac_erronnees.calc_date_moyenne(dates);
END;
Update: Second thing is that DateArrayVar has scope only within the package that you have created, in the anonymous block, Oracle cannot see that declaration. One solution is to create external type that is visible to all other procedures and anonymous block or to test, create a procedure within the package and call it from out side.
create or replace
PACKAGE TRANSAC_ERRONNEES AS
TYPE dateArrayVar IS TABLE OF DATE;
FUNCTION calc_date_moyenne(dateArrayIn dateArrayVar
) RETURN DATE;
PROCEDURE test;
END TRANSAC_ERRONNEES;
/
CREATE OR REPLACE PACKAGE BODY TRANSAC_ERRONNEES AS
FUNCTION calc_date_moyenne(dateArrayIn datearrayvar) RETURN DATE IS
dateFinal DATE;
tempsEnSeconde NUMBER;
tempsMoyenEnSeconde NUMBER;
BEGIN
tempsEnSeconde := 0;
tempsMoyenEnSeconde := 0;
FOR i IN 1..dateArrayIn.count loop
tempsEnSeconde := to_number(to_char(dateArrayIn(i), 'HH24')) * 60 * 60 + to_number(to_char(dateArrayIn(i), 'MI')) * 60 + to_number(to_char(dateArrayIn(i), 'SS'));
tempsMoyenEnSeconde := tempsMoyenEnSeconde+tempsEnSeconde;
end loop;
tempsMoyenEnSeconde := tempsMoyenEnSeconde/dateArrayIn.count;
dateFinal := to_date(TO_CHAR(dateArrayIn(1),'DD-MM-YYYY') || ' ' || TO_CHAR(to_date(tempsMoyenEnSeconde,'sssss'), 'HH24:MI:SS'), 'DD-MM-YYYY HH24:MI:SS');
dbms_output.put_line(TO_CHAR(dateFinal,'DD-MM-YYYY HH24:MI:SS'));
RETURN dateFinal;
END calc_date_moyenne;
PROCEDURE test
dates dateArrayVar;
resultat DATE;
BEGIN
dates.extend(2); -- Since you want to assign two values, extend by 2
dates(1) := SYSDATE;
dates(2) := SYSDATE;
resultat := transac_erronnees.calc_date_moyenne(dates);
END;
END TRANSAC_ERRONNEES;
/
And to test, call it as
BEGIN
TRANSAC_ERRONNEES.TEST;
END;
/
DateArrayVar has scope only within the package
I found the solution : I had to specifiate the package : TRANSAC_ERRONNEES.dateArrayVar;
So :
DECLARE
dates TRANSAC_ERRONNEES.dateArrayVar;
resultat DATE;
BEGIN
dates := TRANSAC_ERRONNEES.dateArrayVar(SYSDATE, SYSDATE);
resultat := transac_erronnees.calc_date_moyenne(dates);
dbms_output.put_line(TO_CHAR(resultat,'DD-MM-YYYY HH24:MI:SS'));
END;
It's works now, Thanks

Oracle PL/SQL: Error returned without value on function

I'm trying to create a function that will compute for factorial but it returns an error when I do a SELECT FACTORIAL('1') FROM DUAL;
It returns the heinous error:function returned without value. I tried adding an exception but it seems that it doesn't work either. Care to help?
CREATE OR REPLACE FUNCTION FACTORIAL(p_factorial INTEGER)
RETURN NUMBER
AS var_fnumber number(2);
ctr number(2);
var_contain number(2) := 1;
BEGIN
FOR ctr in 1..p_factorial
LOOP
BEGIN
var_contain := var_contain * ctr;
DBMS_OUTPUT.put_line(var_contain);
EXCEPTION
WHEN OTHERS THEN
RETURN 0;
END;
END LOOP;
END; --FACTORIAL;
/
You MUST return something in a function.
SQL> CREATE OR REPLACE
2 FUNCTION FACTORIAL(
3 p_factorial INTEGER)
4 RETURN NUMBER
5 AS
6 var_fnumber NUMBER(2);
7 ctr NUMBER(2);
8 var_contain NUMBER(2) := 1;
9 BEGIN
10 FOR ctr IN 1..p_factorial
11 LOOP
12 BEGIN
13 var_contain := var_contain * ctr;
14 END;
15 END LOOP;
16 RETURN var_contain;
17 END;
18 /
Function created.
SQL>
SQL> SELECT factorial(2) FROM dual
2 /
FACTORIAL(2)
------------
2
For more details, read http://lalitkumarb.wordpress.com/2014/05/01/ora-06503-plsql-function-returned-without-value/
CREATE OR REPLACE FUNCTION FACTORIAL(p_factorial INTEGER)
RETURN NUMBER
AS var_fnumber number;
ctr number;
var_contain number := 1;
BEGIN
FOR ctr in 1..p_factorial
LOOP
BEGIN
var_contain := var_contain * ctr;
EXCEPTION
WHEN OTHERS THEN
RETURN 0;
RETURN var_contain;
END;
END LOOP;
RETURN var_contain;
END; --FACTORIAL;
/
Was gonna say that I found it. Thank you for the answers.
As for the reason why I used varchar2, I wasn't finalizing it yet.
modified your code try this:
create or replace
FUNCTION FACTORIAL(p_factorial INTEGER)
RETURN VARCHAR2
AS
var_contain varchar2(50):= 1;
BEGIN
FOR ctr in 1..p_factorial
LOOP
var_contain := var_contain * ctr;
END LOOP;
EXCEPTION
WHEN OTHERS THEN
RETURN O;
return var_contain;

how can we get the value of of VARRAY from IN Parameter in procedure

I am new to PL/SQL... In Varray how can i get multiple value from IN parameter..... else Is there another ways to get the values...
I want to interate the values through VArray... if any other options then its fine..
coding:
CREATE OR REPLACE
PROCEDURE dynamic_query_build(
vr_plan_sku_id IN VARCHAR2 )
IS
type plan_sku_id_array IS VARRAY(999) OF VARCHAR2(5000);
plan_sku_id plan_sku_id_array;
total INTEGER;
vrx_plan_sku_id VARCHAR2(3000);
BEGIN
vrx_plan_sku_id:= REPLACE(vr_plan_sku_id,',',chr(39)||','||chr(39));
plan_sku_id := plan_sku_id_array(chr(39)||vrx_plan_sku_id||chr(39));
total := plan_sku_id.count;
FOR i IN 1 .. total
LOOP
dbms_output.put_line(plan_sku_id(i));
END LOOP;
EXCEPTION
WHEN OTHERS THEN
raise_application_error(-20001,'An error was encountered - '||SQLCODE||' -ERROR- '||SQLERRM);
END dynamic_query_build;
Execution:
set serveroutput on;
declare
vr_plan_sku_id varchar2(200) := '5863314,5863315';
BEGIN
dynamic_query_build(vr_plan_sku_id);
END;
/
My Output:
anonymous block completed
'5863314','5863315'
Expected output:
5863314
5863315
now it is considering as single value....
I created anonymous block with procedure dynamic_query_build. Added there code, that will split VARCHAR2 variable into varray.
I think, the key to your question is this line - plan_sku_id.EXTEND();
You can extend varray dynamically, but only till it reaches defined maximum (in your case - 999).
DECLARE
vr_plan_sku_id varchar2(200) := '5863314,5863315';
PROCEDURE dynamic_query_build(
vr_plan_sku_id IN VARCHAR2 )
IS
type plan_sku_id_array IS VARRAY(999) OF VARCHAR2(5000);
plan_sku_id plan_sku_id_array;
total INTEGER;
position PLS_INTEGER := 0;
last_position PLS_INTEGER := 1;
tmp VARCHAR2(5000);
counter PLS_INTEGER := 1;
BEGIN
plan_sku_id := plan_sku_id_array();
LOOP
position := INSTR(vr_plan_sku_id, ',', last_position);
IF position > 0 THEN
tmp := SUBSTR(vr_plan_sku_id, last_position, position - last_position);
last_position := position + 1;
ELSE
tmp := SUBSTR(vr_plan_sku_id, last_position);
END IF;
plan_sku_id.EXTEND();
plan_sku_id(counter) := tmp;
counter := counter + 1;
EXIT WHEN position = 0 OR counter > 10;
END LOOP;
total := plan_sku_id.count;
FOR i IN 1 .. total
LOOP
dbms_output.put_line(plan_sku_id(i));
END LOOP;
EXCEPTION
WHEN OTHERS THEN
raise_application_error(-20001,'An error was encountered - '||SQLCODE||' -ERROR- '||SQLERRM);
END dynamic_query_build;
BEGIN
dynamic_query_build(vr_plan_sku_id);
END;
/
Put a replace in the dbms_output statement this will eliminate the quotes from the string
....
dbms_output.put_line replace (replace (plan_sku_id(i), '''' ))',',chr(10);
.....