There seems to be a contradiction in what you've said, but the flow isn't very clear. You have a procedure (P_USER_TIME
?) which is called from a function (unnamed). Your procedure (and it would be helpful to at least see how that's declared) takes a string argument, but you are passing it a date
, not a varchar2
value. Since we don't have your actual procedure, let's make one up:
create or replace procedure p_user_time(p_time varchar2) is
l_time date;
begin
dbms_output.put_line('Parameter p_time: ' || p_time);
l_time := to_date(p_time, 'DD-MON-YYYY HH24:MI:SS');
dbms_output.put_line('Converted l_time: ' ||
to_char(l_time, 'DD-MON-YYYY HH24:MI:SS'));
end;
/
If I call that with the string you're passing as plsql_block
I get:
alter session set nls_date_format = 'DD-MON-YYYY';
set serveroutput on
exec P_USER_TIME(to_date('21-JUL-2012 03:30:30','DD-MON-YYYY HH24:MI:SS'));
Session altered.
Parameter p_time: 21-JUL-2012
Converted l_time: 21-JUL-2012 00:00:00
PL/SQL procedure successfully completed.
So the time portion is lost. You're converting a string representing the date into a date
object, and when it's passed to the procedure it's being implicitly converted back to a string using your default NLS_DATE_FORMAT mask, which I've guessed is probably DD-MON-YYYY
; so this is equivalent to doing:
exec P_USER_TIME(to_char(to_date('21-JUL-2012 03:30:30','DD-MON-YYYY HH24:MI:SS')));
Doing to_char(to_date(...))
looks redundant, but because you have an explicit data mask one way and an implicit one the other, it's probably not doing what you expect.
Assuming the P_USER_TIME
procedure is expecting the date/time string in the specific format you're passing, you should just pass the string, not try to convert it yourself:
exec P_USER_TIME('21-JUL-2012 03:30:30');
Parameter p_time: 21-JUL-2012 03:30:30
Converted l_time: 21-JUL-2012 03:30:30
PL/SQL procedure successfully completed.
You also have a function that's calling the procedure dynamically. Again, let's make one up:
create or replace function f_foo return number is
ln_dbms_cur number;
ret_int number;
plsql_block varchar2(256);
begin
plsql_block := 'BEGIN P_USER_TIME(to_date(''21-JUL-2012 03:30:30'',''DD-MON-YYYY HH24:MI:SS'')); END;';
ln_dbms_cur := DBMS_SQL.OPEN_CURSOR;
DBMS_SQL.PARSE(ln_dbms_cur, plsql_block, DBMS_SQL.NATIVE);
ret_int := DBMS_SQL.EXECUTE(ln_dbms_cur);
DBMS_SQL.CLOSE_CURSOR(ln_dbms_cur);
return ret_int;
end;
/
var rc number;
exec :rc := f_foo;
Parameter p_time: 21-JUL-2012
Converted l_time: 21-JUL-2012 00:00:00
PL/SQL procedure successfully completed.
So the same thing happens. If the construction of plsql_block
is simplified to:
plsql_block := 'BEGIN P_USER_TIME(''21-JUL-2012 03:30:30''); END;';
then you get:
Parameter p_time: 21-JUL-2012 03:30:30
Converted l_time: 21-JUL-2012 03:30:30
PL/SQL procedure successfully completed.
Reading the question again, it may actually be a much simpler underlying problem.
You said '... string argument to which I pass the current date in string format using the to_date function'.
If that's interpreted literally, it suggests you might just be using to_date
when you should have to_char
;
if you really want the current time that would make the line in the function something like:
plsql_block := 'BEGIN P_USER_TIME(to_char(sysdate, ''DD-MON-YYYY HH24:MI:SS'')); END;';
Or using the direct call to the procedure:
exec P_USER_TIME(to_char(sysdate, 'DD-MON-YYYY HH24:MI:SS'));
Parameter p_time: 31-JUL-2012 09:38:43
Converted l_time: 31-JUL-2012 09:38:43
PL/SQL procedure successfully completed.
Edited to look at the Java code posted as a comment
Your function now seems to take two arguments, one of which is the block you want to execute; and return a cursor. I'm going to guess (again) that the cursor is returning what's been inserted, so I've changed my dummy procedure to insert the date/time into a table, and my function to retrieve that. This would be a lot easier if you posted a complete set of code that demonstrates the problems you're seeing, of course.
create or replace procedure p_user_time(p_time varchar2) is
l_time date;
begin
dbms_output.put_line('Parameter p_time: ' || p_time);
l_time := to_date(p_time, 'DD-MON-YYYY HH24:MI:SS');
dbms_output.put_line('Converted l_time: ' ||
to_char(l_time, 'DD-MON-YYYY HH24:MI:SS'));
insert into cooldude values(l_time);
end;
/
create or replace function f_foo(pNumber number, p_plsql_block in varchar2)
return sys_refcursor is
ln_dbms_cur number;
ret_int number;
plsql_block varchar2(256);
rc sys_refcursor;
begin
ln_dbms_cur := DBMS_SQL.OPEN_CURSOR;
DBMS_SQL.PARSE(ln_dbms_cur, p_plsql_block, DBMS_SQL.NATIVE);
ret_int := DBMS_SQL.EXECUTE(ln_dbms_cur);
DBMS_SQL.CLOSE_CURSOR(ln_dbms_cur);
open rc for select * from cooldude;
return rc;
end;
/
I can still call that from SQL*Plus with no problems. And I can have a Java program execute it:
import java.sql.*;
import java.text.*;
import oracle.jdbc.*;
import oracle.jdbc.pool.OracleDataSource;
public class Cooldude
{
public static void main(String args[]) throws SQLException
{
String plSqlBlk = "BEGIN P_USER_TIME(to_char(sysdate, 'DD-MON-YYYY HH24:MI:SS')); END;";
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Connection conn;
OracleDataSource ds = new OracleDataSource();
ds.setURL("jdbc:oracle:thin:scott/oracle@127.0.0.1:1521:orcl");
conn = ds.getConnection();
CallableStatement cstmt = null;
ResultSet rs = null;
String output = "";
System.out.println("******calling SP *******");
cstmt = conn.prepareCall("{? = call f_foo(?,?)}");
cstmt.setFetchSize(10000);
cstmt.registerOutParameter(1, OracleTypes.CURSOR);
cstmt.setInt(2, 204149885);
cstmt.setString(3, plSqlBlk);
cstmt.executeQuery();
rs = (ResultSet) cstmt.getObject(1);
while (rs.next())
{
Timestamp ts = rs.getTimestamp(1);
System.out.println(sdf.format(ts));
}
if ( conn != null )
{
try { conn.close(); } catch ( Exception ex ) {}
conn = null;
}
}
}
javac Cooldude.java && java Cooldude
******calling SP *******
2012-08-11 09:45:07
2012-08-11 09:46:04
2012-08-11 09:54:33
Which seems to be fine; this has the output from three calls to the Java program.
You haven't said quite why you think the time is being truncated in your Java code. I'll go even further out on a limb... are you basing that on the display from your Java showing it as 00:00:00
; and if so, are you using rs.getDate()
instead of rs.getTimestamp
? java.sql.Date
doesn't have a time portion, unlike java.util.Date
. (See this question for example).