Skip to Main Content
  • Questions
  • How to get a date including millisecond in PL/QL

Breadcrumb

Question and Answer

Tom Kyte

Thanks for the question, minnie.

Asked: June 22, 2000 - 10:18 am UTC

Last updated: June 26, 2006 - 7:49 am UTC

Version: Oracle 8i 8.1.5

Viewed 10K+ times! This question is

You Asked

Hi,Tom
Our application needs to get a date value including millisecond in PL/SQL packages,but the date datatype in Oracle doesn't support millisecond. Do you have some ideas to solve this kind of problem?

I appreciate your helps about my previous questions.
I have solved my problems according to your methods.

thank you again.


minnie
software engineer
Mediol online,Inc.





and Tom said...

2 solutions:

1) write a java stored procedure. java has time functionality that is much more granular then the Oracle DATE type. This will work in 8.1.5 and up. It can look like this:

ops$tkyte@DEV8I.WORLD> CREATE or replace JAVA SOURCE
2 NAMED "MyTimestamp"
3 AS
4 import java.lang.String;
5 import java.sql.Timestamp;
6
7 public class MyTimestamp
8 {
9 public static String getTimestamp()
10 {
11 return (new
12 Timestamp(System.currentTimeMillis())).toString();
13 }
14 };
15 /

Java created.

ops$tkyte@DEV8I.WORLD> create or replace function my_timestamp return varchar2
2 AS LANGUAGE JAVA
3 NAME 'MyTimestamp.getTimestamp() return java.lang.String';
4 /

Function created.


ops$tkyte@DEV8I.WORLD> l
1* select my_timestamp, to_char(sysdate,'yyyy-mm-dd hh24:mi:ss') from dual
ops$tkyte@DEV8I.WORLD> /

MY_TIMESTAMP
----------------------------------------------------------------------------------------------------
TO_CHAR(SYSDATE,'YY
-------------------
2000-06-22 13:47:53.376
2000-06-22 13:47:53


ops$tkyte@DEV8I.WORLD>


2) use an external procedure written in C. C has api's to the system that allow for much more granular time components. This will work in 8.0 and up. For example if you run something like:

ops$tkyte@DEV8I.WORLD> create or replace library timelib as
2 '/export/home/tkyte/src/t/extproc.so'
3 /
Library created.

ops$tkyte@DEV8I.WORLD> create or replace
2 procedure get_extended_time( p_timestring out varchar2 )
3 is external
4 name "get_extended_time"
5 library timelib
6 language C
7 with context
8 parameters ( CONTEXT,
9 p_timestring STRING,
10 p_timestring INDICATOR short,
11 p_timestring MAXLEN int,
12 p_timestring LENGTH int );
13
14 /

Procedure created.
ops$tkyte@DEV8I.WORLD> declare
2 l_timestring varchar2(30);
3 begin
4 get_extended_time( l_timestring );
5 dbms_output.put_line(
to_char( sysdate, 'mm/dd/yy hh24:mi:ss' ) );
6 dbms_output.put_line( l_timestring );
7 end;
8 /
06/22/00 13:26:28
06/22/00 13:26:28.103243

PL/SQL procedure successfully completed.

In sqlplus after compiling the following C code into a .so or .dll or .sl (depending on platform) you can get the milliseconds.

Here is the C code:

#include <stdio.h>
#include <stdarg.h>
#include <time.h>

#ifndef OCI_ORACLE
# include <oci.h>
#endif


#define raise_application_error return raise_application_error_x

static long raise_application_error_x( OCIExtProcContext * ctx,
int errCode,
char * errMsg, ...)
{
char msg[8192];
va_list ap;

va_start(ap,errMsg);
vsprintf( msg, errMsg, ap );
va_end(ap);

OCIExtProcRaiseExcpWithMsg(ctx,errCode,msg,strlen(msg));
return -1;
}

long
get_extended_time( OCIExtProcContext * ctx,
char * p_data,
short * p_data_i,
int * p_data_maxl,
int * p_data_l )
{
struct timeval tp;

if ( *p_data_maxl < 25 )
raise_application_error( ctx, 20001,
"String must be 25 bytes or more" );

gettimeofday(&tp, NULL);
cftime( p_data, "%D %T", &tp.tv_sec );
sprintf( p_data+strlen(p_data), ".%d", tp.tv_usec );

*p_data_l = strlen(p_data);
*p_data_i = 0;

return 0;
}

Rating

  (6 ratings)

Is this answer out of date? If it is, please let us know via a Comment

Comments

or this in 9i

steveh, November 02, 2001 - 10:11 am UTC

select current_timestamp from dual;

A reader, November 19, 2001 - 12:27 pm UTC

Could use some compilation instructions

Milliseconds in Oracle

Kamlesh, January 11, 2002 - 1:59 am UTC

It helped me a lot in retrieving miliseconds in oracle



Extract Only the MILLISEC part

Pascal, February 20, 2002 - 11:40 am UTC

Hi Tom,

Thanks for My_Timestamp JSP.

I have tried to Exract only the Millisec part , but you can see from the Query
below that there's some LAG ...now , how do i Extract only the Millisec without
this LAG.


column my_timestamp format a30
column millisec format a30
select substr(my_timestamp,instr(my_timestamp,'.')+1 ) millisec , my_timestamp
from dual;


MILLISEC MY_TIMESTAMP
------------------------------ -----------------------------
594 2002-02-20 19:34:26.596


Thanks in advance


Best Regards


Pascal





Need a make file,

Mogan, May 10, 2002 - 2:15 pm UTC

I tried to compile this in SunSolaris 5.6 With oracle 8.1.7. My make file is giving some trouble.
Could you please give me the make for this C code. Thanks,

Tom Kyte
May 10, 2002 - 4:35 pm UTC

MAKEFILE= $(ORACLE_HOME)/rdbms/demo/demo_rdbms.mk

INCLUDE= -I$(ORACLE_HOME)/rdbms/demo \
-I$(ORACLE_HOME)/rdbms/public \
-I$(ORACLE_HOME)/plsql/public \
-I$(ORACLE_HOME)/network/public

all: extproc.so

include $(MAKEFILE)

CC=cc

extproc.so: extproc.c extproc.o
$(MAKE) -f $(MAKEFILE) extproc_callback \
SHARED_LIBNAME=extproc.so OBJS="extproc.o"

CFLAGS= -g -I. $(INCLUDE)

how can I get it in SQL

parag jayant patankar, June 26, 2006 - 3:25 am UTC

Hi Tom,

I have two questions for you. I am in 9.2 db.

Q1. We are designing database. In this one of the table has to store "TIMESTAMP" ( including multiseconds ) to later do date calculation  in multiseconds/seconds/months/years. I have selected datatype "TIMESTAMP". Is it correct ? Or Do you want to suggest another datatype ?

2.  From this table I want to able to extract data using simple SQL for user input years, months, seconds and multiseconds

12:38:42 SQL> create table t ( a timestamp );

Table created.

insert into t values (localtimestamp);
...
insert into t values (localtimestamp);
...
insert into t values (localtimestamp);

How can I write SQL to get "localtimestamp -a" in miliseconds, seconds, months and years.  SO I can give

select a 
from t
where < localtimestame - a duration in multiseconds/seconds ..etc > > 60

So It wll give me details more than 60 seconds/miliseconds..etc  from now ?

I have tried with numtodsinterval but not successful. I am sure it is possible with some simple SQL, but sorry I could not make it.

Kindly help me as usual.

thanks & regards
pjp 

Tom Kyte
June 26, 2006 - 7:49 am UTC

1) that would be the correct datatype, unless you also needed timezone support, then it would be timestamp with timezone perhaps.

2) 

ops$tkyte@ORA10GR2> create table t ( a timestamp );
 
Table created.
 
ops$tkyte@ORA10GR2> insert into t values ( systimestamp );
 
1 row created.
 
ops$tkyte@ORA10GR2> select systimestamp - a, numtodsinterval( 60/1000, 'second') from t
  2   where systimestamp - a >= numtodsinterval( 60/1000, 'second')
  3  /
 
no rows selected
 
ops$tkyte@ORA10GR2> exec dbms_lock.sleep( 1 );
 
PL/SQL procedure successfully completed.
 
ops$tkyte@ORA10GR2> select systimestamp - a, numtodsinterval( 60/1000, 'second') from t
  2   where systimestamp - a >= numtodsinterval( 60/1000, 'second')
  3  /
 
SYSTIMESTAMP-A
---------------------------------------------------------------------------
NUMTODSINTERVAL(60/1000,'SECOND')
---------------------------------------------------------------------------
+000000000 00:00:01.002384
+000000000 00:00:00.060000000
 
 

More to Explore

PL/SQL demos

Check out more PL/SQL tutorials on our LiveSQL tool.

PL/SQL docs

PL/SQL reference manual from the Oracle documentation library