How to get the current date time in plsql? - oracle

My Code:
DECLARE
BEGIN
-- outputs 06-DEC-18
dbms_output.put_line(sysdate);
-- also outputs 18-DEC-06
dbms_output.put_line(to_date(sysdate,'yyyy-mm-dd hh24:mi:ss'));
END;
/
The output only shows the date. I want to get also the time.

SYSDATE does have a time component. The first one outputs 06-DEC-18 because your session's parameter NLS_DATE_FORMAT is set to DD-MON-YY.
You have these options.
use TO_CHAR
dbms_output.put_line(TO_CHAR(SYSDATE,'yyyy-mm-dd hh24:mi:ss'));
Modify NLS_DATE_FORMAT to show time.
ALTER SESSION SET NLS_DATE_FORMAT='yyyy-mm-dd hh24:mi:ss';
BEGIN
dbms_output.put_line(SYSDATE);
END;
/
Or use SYSTIMESTAMP to show higher precision of time like milliseconds.
BEGIN
dbms_output.put_line(SYSTIMESTAMP);
END;
/

You can use SYSTIMESTAMP
SELECT SYSTIMESTAMP
FROM DUAL

To convert date type to string with some format use to_char
to_char(sysdate::timestamp, 'YYYY-MM-DD HH24:MI:SS')

Related

Converting an Oracle Stored Procedure DATE Input Parameter

I am very new to Oracle and have a question about input parameters to a stored procedure. Basically its a stored procedure being called from an external system passing in a date formatted as MM/DD/YYYY.
Oracle doesn't seem to like the MM/DD/YYYY format as it gives me a "not a valid month" error. (I think it wants like a DD-MMM-YYYY?) whatever the default is.
is there a way to convert the date as it comes into the procedure without getting an error?
such as:
create procedure test_proc
(
v_input_date IN DATE := to_char(v_input_date, 'MM/DD/YYYY')
)
I know the above code likely makes no actual sense but hopefully it will convey what I'd like to do. The user would call the procedure something like
BEGIN
test_proc('01/01/2018')
END
You may try with ANSI type date 'yyyy-mm-dd' formatting like in the following sample :
SQL>create or replace procedure test_proc( v_input_date date ) is
v_diff int;
begin
v_diff := trunc(sysdate)-v_input_date;
dbms_output.put_line(v_diff||' days difference...');
end;
/
SQL> set serveroutput on;
SQL> begin
test_proc(date '2018-03-21');
end;
/
2 days difference...
Your problem is not in the procedure, it is in the code calling the procedure.
'01/01/2018' is not a date it is a string but your procedure expects a date; however, Oracle tries to be helpful and will implicitly try to convert the string to a date using the TO_DATE( string_value, format_model ) function. Since it does not have a specified format model, it will use the default format for a date which is the NLS_DATE_FORMAT session parameter and if this format mask does not match the format of the string then you will get an error.
(Note: session parameters are per-user-session and can be changed by each user so you should not rely on them being the same for each user or even the same between sessions for the same user!)
You can see the format of the NLS_DATE_FORMAT session parameter using the query:
SELECT VALUE
FROM NLS_SESSION_PARAMETERS
WHERE PARAMETER = 'NLS_DATE_FORMAT';
And your code to call the procedure is implicitly being converted to something like:
BEGIN
test_proc(
TO_DATE(
'01/01/2018',
( SELECT VALUE FROM NLS_SESSION_PARAMETERS WHERE PARAMETER = 'NLS_DATE_FORMAT' )
)
);
END;
To generate a date you should explicitly convert the string to a date either by:
Using an ANSI literal
BEGIN
test_proc( DATE '2018-01-01' );
END;
Or by specifying the format mask used in the conversion
BEGIN
test_proc( TO_DATE( '01/01/2018', 'MM/DD/YYYY' ) );
END;

Oracle Datetime difference issue with AM/ PM

I have the following stored procedure which calculates the time taken for a merge statement
create or replace procedure ModAuditData(
O_UpdatedCount out int
,O_EndTime out timestamp
,O_Duration out int)
as
P_StartTime timestamp(3) WITH LOCAL TIME ZONE;
-- EndTime timestamp;
begin
P_StartTime:=to_timestamp(to_char(current_timestamp,'DD/MM/YYYY HH:MI:SS'),'DD/MM/YYYY HH:MI:SS');
-- merge Statment that does UPSERT
O_UpdatedCount :=SQL%ROWCOUNT;
commit;
O_EndTime:=to_timestamp(to_char(current_timestamp,'DD/MM/YYYY HH:MI:SS'),'DD/MM/YYYY HH:MI:SS');
begin
select extract( second from (O_EndTime-P_StartTime) )
into O_Duration
from dual;
Exception When others then
O_Duration:=0;
end;
end ModAuditData;
The Issue is
O_EndTime:=to_timestamp(to_char(current_timestamp,'DD/MM/YYYY HH:MI:SS'),'DD/MM/YYYY HH:MI:SS')
gives exact opposite of
P_StartTime:=to_timestamp(to_char(current_timestamp,'DD/MM/YYYY HH:MI:SS'),'DD/MM/YYYY HH:MI:SS');
in terms of AM/PM
What is the correct way to calculate the start and end time
CURRENT_TIMESTAMP is already a TIMESTAMP WITH TIME ZONE, there is no reason to convert it first to VARCHAR2 and then back again into a TIMESTAMP.
Also timestamp(3) (which provides precision up to millisecond) does not make much sense when you return duration as INTEGER, i.e. full seconds.
Try it like this:
P_StartTime timestamp(3) WITH TIME ZONE;
begin
P_StartTime := current_timestamp;
-- merge Statment that does UPSERT
O_UpdatedCount :=SQL%ROWCOUNT;
commit;
O_Duration := EXTRACT(SECOND FROM (current_timestamp - P_StartTime));
end;
In case of SQL*Plus consider to use TIMING command.

Timestamp AT TIME ZONE in SQL

I'm getting a strange error when trying to convert TIMESTAMP value to a timezone given as parameter (variable).
The code below throws ORA-00907 exception:
ORA-00907: missing right parenthesis
declare
tz timestamp := current_timestamp;
v_timezone varchar2(100) := '03:00';
tz2 timestamp;
begin
-- select (tz at time zone '03:00') into tz2 from dual;
select (tz at time zone v_timezone)
into tz2
from dual;
dbms_output.put_line(to_char(tz2,'hh24:mi:ss'));
-- dbms_output.put_line(to_char((tz at time zone v_timezone),'hh24:mi:ss'));
end;
At the same time, both SQL with string literal (first commented line) and PL/SQL with variable (second commented line) work just fine.
What could be the issue with variable in SQL? And why ORA-00907?
You need to just enclose the v_timezone variable inside braces (), see your code as below
declare
tz timestamp := current_timestamp;
v_timezone varchar2(100) := '03:00';
tz2 timestamp;
begin
-- select (tz at time zone '03:00') into tz2 from dual;
-- either use it as
-- select tz at time zone (v_timezone)
-- or
-- select (tz at time zone (v_timezone) )
select (tz at time zone (v_timezone) )
into tz2
from dual;
dbms_output.put_line(to_char(tz2,'hh24:mi:ss'));
-- dbms_output.put_line(to_char((tz at time zone v_timezone),'hh24:mi:ss'));
end;
AT TIME ZONE requires a literal or an expression:
expr AT
{ LOCAL
| TIME ZONE { ' [ + | - ] hh:mi'
| DBTIMEZONE
| 'time_zone_name'
| expr
}
}
It doesn't like a variable. It seems that the variable is being implicitly seen as an expression inside the dbms_output call, or any PL/SQL context (as Wernfried pointed out, just tz2 := tz at time zone v_timezone works too), which is a bit strange; but the same thing isn't happening in a SQL context.
You can just force your variable into an expression by enclosing that in parentheses, or call a dummy function:
declare
tz timestamp := current_timestamp;
v_timezone varchar2(100) := '03:00';
tz2 timestamp;
begin
-- select (tz at time zone '03:00') into tz2 from dual;
select tz at time zone (v_timezone)
into tz2
from dual;
dbms_output.put_line(to_char(tz2,'hh24:mi:ss'));
-- dbms_output.put_line(to_char((tz at time zone v_timezone),'hh24:mi:ss'));
end;
PL/SQL procedure successfully completed.
17:45:41
Essentially, remove the redundant parentheses you have now, and use dummy ones around the variable. You can use a function instead, like upper(v_timezone), but it isn't necessary - just the parentheses to make it be evaluated as an expression are enough. Strange but works... It's mentioned in bug 6113282 and seems to worked like this since 9i.

Character to number conversion error in trigger

How will the trigger insert between two timings? Getting character to number conversion error in the if condition while inserting. Below is my trigger.
create or replace trigger TRI_INSERT
after insert on stud_details
referencing old as old new as new
for each row
declare
strTime varchar2(20) := :new.time_stamp; -- (eg: '02/08/2013 11:09:42 PM')
begin
if (to_char(strTime, 'hh24:mi:ss') between '22:00:00' and '23:59:59') then
insert into stud_clas_details
(id,
v-id,
w-id,
al_id,
time,
Time_Stamp)
values
(seq_ve_id.nextval,
:new.vehicle_id,
:new.way_id,
'xxxx',
strTime,
sysdate);
end if;
end TRI_INSERT;
you cannot to_char() a varchar2 with a date format and expect it to work.
instead you should do
if (to_char(:new.time_stamp, 'hh24:mi:ss') between '22:00:00' and '23:59:59') then
also if you want to insert the time into the table in a specific format, use
to_char(:new.time_stamp, 'hh24:mi:ss')
as with
strTime varchar2(20) := :new.time_stamp;
you will just be inserting the date in whatever the default NLS_DATE_FORMAT is for that session (which may vary per session).
How about instead using:
if extract(hour from :new.time_stamp) in (22,23) then ...
Problem in the if condition.. Now its working fine.. Thanks for all.
create or replace trigger TRI_INSERT
after insert on stud_details
referencing old as old new as new
for each row
declare
strTime varchar2(20) := :new.time_stamp; -- (eg: '02/08/2013 11:09:42 PM')
strFromTime varchar2(20):= '22:00:00'
strToTime varchar2(20):= '23:59:59'
begin
if ((to_char(strTime, 'hh24:mi:ss') > strFromTime) and (to_char(strTime,
'hh24:mi:ss') < strToTime)) then
insert into stud_clas_details
(id,
v-id,
w-id,
al_id,
time,
Time_Stamp)
values
(seq_ve_id.nextval,
:new.vehicle_id,
:new.way_id,
'xxxx',
strTime,
sysdate);
end if;
end TRI_INSERT;

How to format a Date variable in PLSQL

I am new to PL/SQL and have this question.
I created a procedure with the following specification:
PROCEDURE runschedule (i_RunDate IN DATE)
this i_RunDate comes in a specific format, and I need to change it to this format:
'MM/dd/yyyy hh:mi:ss PM'
I couldn't find how to re-format a Date variable.
You need to use the TO_CHAR function. Here's an example:
SELECT TO_CHAR(CURRENT_TIMESTAMP, 'MM/DD/YYYY HH12:MI:SS AM') FROM dual;
The DATE has not especific format, a DATE is a DATE. When stored in the database column, date values include the time of day in seconds since midnight, and a DATE variable has the same, only that when in some point you show the variable is formatted. PL/SQL can convert the datatype of a value implicitly, for example, can convert the CHAR value '02-JUN-92' to a DATE value.. but I don't recommend you rely on this implicit conversiosn. I always use the explicit conversion.
For more on this topic, you could read this:
http://download.oracle.com/docs/cd/B28359_01/appdev.111/b28370/datatypes.htm#i9118
In your case, if you want to format your DATE to log something, or to show in your UI or wathever in a different format, you need to assig it to a varchar variable as Justin said, something like this:
....
v_generated_run_date DATE;
v_var_date VARCHAR2(30);
BEGIN -- generate sysdate if required
IF (i_RunDate is null)
THEN
v_var_date:=TO_CHAR(sysdate, 'MM/DD/YYYY HH12:MI:SS AM');
ELSE
v_var_date:=TO_CHAR(i_RunDate,'MM/DD/YYYY HH12:MI:SS AM');
END IF;
pkgschedule.createschedule (v_var_date);
commit;
END runschedule;
END
Your createschedule procedure, in this case, will have a varchar2 parameter...

Resources