how to add HH:MI to systimestamp in PLSQL code with a HH:MI as variable - plsql

I want to replace '02:00' with a variable in the below code in PLSQL procedure.
SELECT SYSTIMESTAMP + interval '02:00' HOUR TO MINUTE
INTO est_close_date
FROM DUAL;

Define the variable as the number of hours, then you can do:
declare
l_number_of_hours integer;
...
begin
...
l_number_of_hours := 6;
SELECT SYSTIMESTAMP + interval '1' HOUR * l_number_of_hours
INTO est_close_date
FROM DUAL;
end;
If you need finer granularity, use minutes:
declare
l_number_of_minutes integer;
...
begin
...
l_number_of_minutes := 2 * 60 + 30;
SELECT SYSTIMESTAMP + interval '1' minute * l_number_of_minutes
INTO est_close_date
FROM DUAL;
end;

Related

Adding hours after midnight today

Im trying to add hours to midnight of today eg: like 27 hours
I have tried various methods from the internet but am getting the trunc of the dated expected. eg 23-nov-2022 not 23-nov-2022 03:00. when i run it outside my pl/sql procedure/block i get the desired output
the select:
select to_char(to_date(sysdate,'DD-MON-RRRR HH:MI')+hours/24,'DD-MON-RRRR HH:MI') into v_from from dual;
I need some expert assistance
Add an INTERVAL DAY TO SECOND data type to SYSDATE TRUNCated back to midnight:
DECLARE
v_from DATE;
BEGIN
SELECT TRUNC(sysdate) + INTERVAL '27' HOUR
INTO v_from
FROM DUAL;
DBMS_OUTPUT.PUT_LINE(TO_CHAR(v_from,'DD-MON-RRRR HH:MI'));
END;
/
or, more simply:
DECLARE
v_from DATE;
BEGIN
v_from := TRUNC(sysdate) + INTERVAL '27' HOUR;
DBMS_OUTPUT.PUT_LINE(TO_CHAR(v_from,'DD-MON-RRRR HH:MI'));
END;
/
or, dynamically, with the NUMTODSINTERVAL function:
DECLARE
v_from DATE;
v_hours NUMBER(3,0) := 27;
BEGIN
v_from := TRUNC(sysdate) + NUMTODSINTERVAL(v_hours,'HOUR');
DBMS_OUTPUT.PUT_LINE(TO_CHAR(v_from,'DD-MON-RRRR HH:MI'));
END;
/
fiddle
Trunc SYSDATE to get midnight. Then add hours: 1 hour is 1/24 day so you'd add the number of hours divided by 24. Example.
koen>DECLARE
2 l_date DATE;
3 l_hours NUMBER := 27;
4 BEGIN
5 l_date := TRUNC(SYSDATE) + 27/24;
6 dbms_output.put_line('l_date is: '||TO_CHAR(l_date,'DD-MON-YYYY HH24:MI'));
7 END;
8* /
l_date is: 23-NOV-2022 03:00
PL/SQL procedure successfully completed.
koen>
The select from dual is not advised, you can just assign a variable in pl/sql using the assignment operator :=. The select from dual requires an additional context switch (invoke the sql engine from within pl/sql).

How to convert hours in varchar to complete a date variable in pl/sql?

I need to add a varchar value to my date variable in a stored procedure.
PROCEDURE TEST_CAL
(P_HOURS IN VARCHAR2
,P_DATE IN DATE
)
IS
V_DATE date;
BEGIN
V_DATE := P_DATE;
END;
Now V_DATE's value is 03.10.2022 and P_HOURS's value is '7' and I don't know how to add this value to V_DATE so it's value is 03.10.2022 7am.
Add a multiple of an hour interval:
V_DATE := P_DATE + TO_NUMBER(p_hours) * INTERVAL '1' HOUR;
or, use NUMTODSINTERVAL:
V_DATE := P_DATE + NUMTODSINTERVAL(TO_NUMBER(p_hours), 'HOUR');
or, use arithmetic:
V_DATE := P_DATE + TO_NUMBER(p_hours) / 24;
Even better, pass the hours as a number and not a string:
PROCEDURE TEST_CAL(
P_HOURS IN INTEGER
, P_DATE IN DATE
)
IS
V_DATE date;
BEGIN
V_DATE := P_DATE + p_hours * INTERVAL '1' HOUR;
END;
/
fiddle

Function to generate random date from period [duplicate]

I have this anonymous block:
DECLARE
V_DATA DATE;
BEGIN
V_DATA := '01-GEN-2000';
HR.STATISTICHE.RATINGOPERATORI (V_DATA);
COMMIT;
END;
but I would to generate the date in a random way. How can I do?
You can generate random dates between two dates ,as displayed in the query below .Random Dates are generated between 1-jan-2000 and 31-dec-9999
SELECT TO_DATE(
TRUNC(
DBMS_RANDOM.VALUE(TO_CHAR(DATE '2000-01-01','J')
,TO_CHAR(DATE '9999-12-31','J')
)
),'J'
) FROM DUAL;
OR you can use
SELECT TO_DATE (
TRUNC (
DBMS_RANDOM.VALUE (2451545, 5373484)
)
, 'J'
)
FROM DUAL
In the above example ,the first value is 01-Jan-2000 and the second value id 31-dec-9999
To generate random date you can use
select to_date('2010-01-01', 'yyyy-mm-dd')+trunc(dbms_random.value(1,1000)) from dual
or for random datetime
select to_date('2010-01-01', 'yyyy-mm-dd')+dbms_random.value(1,1000) from dual
If you want to see it's logic, you can also use this code.
create or replace procedure genDate(result out nvarchar2) IS
year number;
month number;
day number;
Begin
year:=FLOOR(DBMS_RANDOM.value(2000,2100));
month:=FLOOR(DBMS_RANDOM.value(1,12));
IF month=2 and (year/4)=0 and (year/100)!=0 then
day:=FLOOR(DBMS_RANDOM.value(1,29));
ELSIF month=2 or (year/100)=0 then
day:=FLOOR(DBMS_RANDOM.value(1,28));
ELSIF MOD(month,2)=1 then
day:=FLOOR(DBMS_RANDOM.value(1,31));
ELSIF MOD(month,2)=0 and month!=2 then
day:=FLOOR(DBMS_RANDOM.value(1,30));
END IF;
result:=month||'-'||day||'-'||year;
End;
here is one more option to generate date going back from now where 365 - days quanitity to move back from today, 'DD.MM.YYYY'- mask
to_char(sysdate-dbms_random.value()*365, 'DD.MM.YYYY')
I needed to generate employee data for testing. Each employee needed a date of birth that put them between 16 and 65 years of age, and a date of hire sometime between their 16th birthday and SYSDATE. Here's how...
FUNCTION randomDateInRange(alpha IN DATE, omega IN DATE) RETURN DATE IS
BEGIN
RETURN alpha + DBMS_RANDOM.VALUE(0, omega - alpha);
END;
...and then, to use this function...
-- an employee can be any age from 16 to 65 years of age
DoB := randomDateInRange(
SYSDATE - INTERVAL '65' YEAR,
SYSDATE - INTERVAL '16' YEAR
);
-- an employee could have been hired any date since their sixteenth birthday
DoH := randomDateInRange(
DoB + INTERVAL '16' YEAR,
SYSDATE
);

Using parameters in procedures

I need to create a procedure that receives as a parameter a month and a year.
Inside the procedure I need to have a query to retrieve some values, that will have to take in account the parameters received.
create or replace procedure GET_REVS(MONTH in VARCHAR2,YEAR in varchar2) is
SELECT
*
FROM
REVENUS_TABLE
WHERE
Y_CODE IN ('YEAR')
AND M_CODE IN ()
Now, M_CODE should have the values since the start of the year until the month received by parameter.
Example if i receive in as parameter for the month a 4 i want my select to like this AND M_CODE IN ('1','2','3','4')
But if i receive MONTH = 3.. i need the select to have AND M_CODE IN ('1','2','3')
So what is the best way to do the procedure in order to be able to do that?
Thanks a lot
You could cast both M_CODE and MONTH as numbers and use BETWEEN operator or just <=:
CREATE OR REPLACE PROCEDURE get_revs(month IN VARCHAR2, year IN VARCHAR2) IS
BEGIN
....
SELECT *
FROM revenus_table
WHERE y_code = year
AND TO_NUMBER(m_code) BETWEEN 1 AND TO_NUMBER(month);
...
END;
You can do some thing like below example to make your procedure more dynamic
CREATE OR REPLACE PROCEDURE get_revs (
MONTH IN VARCHAR2,
YEAR IN VARCHAR2
)
IS
variable_name table_name%ROWTYPE;
v_sql VARCHAR2 (1000)
:= 'SELECT * FROM REVENUS_TABLE WHERE Y_CODE IN ('
|| MONTH
|| ')';
BEGIN
IF MONTH = 4 THEN
v_sql := v_sql || ' and M_CODE IN (''1'',''2'',''3'',''4'')';
END IF;
IF MONTH = 3 THEN
v_sql := v_sql || 'and M_CODE IN (''1'',''2'',''3'')';
END IF;
EXECUTE IMMEDIATE v_sql
INTO variable_name;
END;
Just an alternative to think about.
CREATE OR REPLACE PROCEDURE get_revs(month IN VARCHAR2, year IN VARCHAR2) IS
lv_in_clause VARCHAR2(100 CHAR);
p_ref sys_refcursor;
BEGIN
SELECT 'IN ('
||WMSYS.WM_CONCAT(A.NUM)
||')'
INTO lv_in_clause
FROM
(SELECT ''''
||LEVEL
||'''' NUM,
1 ID1
FROM DUAL
CONNECT BY LEVEL < to_number(MONTH)
)A
GROUP BY a.ID1;
OPEN p_ref FOR 'SELECT *
FROM revenus_table
WHERE y_code = '|| year
||' AND m_code '||lv_in_clause;
END;

How to compare timestamp in PL/SQL

I've this statement:
create table times (time_in timestamp, time_out timestamp);
insert into times values(to_timestamp('02-MAY-11 07.57.00.000000 AM'), to_timestamp('02-MAY-11 07.30.00.000000 PM'));
select extract(hour from(time_out-time_in))||':'||extract(minute from(time_out-time_in)) from times;
EXTRACT(HOURFROM(TIME_OUT-TIME_IN))||':'||EXTRACT(MINUTEFROM(TIME_OUT-TIME_IN))
---------------------------------------------------------------------------------
11:33
And now, I wanna compare the result above. For example:IF [result] > [8 hours] THEN ...
How is to do that?
SELECT *
FROM times
WHERE time_out - time_in > interval '8' hour
Inside a PL/SQL procedure this would look like this:
declare
result interval day to second;
begin
-- !!! make sure this select returns only one row, or use a cursor !!!
select time_out - time_in
into result
from times;
if (result > interval '8' hour) then
dbms_output.put_line('greater');
end if;
end;
/

Resources