TO_DATE Oracle DBMS_SQL.EXECUTE函数问题

时间:2012-07-30 21:46:56

标签: java sql oracle function stored-procedures

我正在尝试使用DBMS_SQL.EXECUTE函数调用Oracle存储过程。我将PL / SQL块作为输入参数传递给使用DBMS_SQL.EXECUTE函数调用DB过程的函数。该过程有一个字符串参数,我使用TO_DATE函数以字符串格式传递当前日期。请参阅下面的我用于调用该过程的语法。调用该过程时,传递的日期将作为DATE数据类型保存在数据库中。我面临的问题是截断日期的时间部分,时间变为12:00 A.M,无论传递给函数的时间如何。有人可以让我知道我做错了什么吗?

用于调用函数的SQL块:

plsql_block =BEGIN P_USER_TIME(to_date('21-JUL-2012 03:30:30','DD-MON-YYYY HH24:MI:SS')); Return; End;

调用过程的函数的SQL语法:

ret_int := DBMS_SQL.OPEN_CURSOR;

DBMS_SQL.PARSE(ret_int,plsql_block,DBMS_SQL.NATIVE);

ret_int_execute := DBMS_SQL.EXECUTE(ln_dbms_cur);

PFB oracle代码块

我正在使用一个将日期作为varchar输入的函数,并且n将它传递给另一个过程。我可以看到过去与日期关联的时间没有插入到某个场景中。请在下面找到我的功能

iv_plsql4 :='10-08-2012 07:30:30';
ln_dbms_cur := DBMS_SQL.OPEN_CURSOR;
iv_plsql2 := BEGIN PKG_PRADEEP.P_INSERTDATE(to_date(iv_plsql4,'DD-MM-YYYY HH24:MI:SS'));

DBMS_OUTPUT.put_line(iv_plsql);
DBMS_SQL.PARSE(ln_dbms_cur,iv_plsql,DBMS_SQL.NATIVE);
ln_cur_execute := DBMS_SQL.EXECUTE(ln_dbms_cur);
This code inserts the date in to the database but the time comes as 12:00 A.M.

但如果我更改了下面给出的字符串iv_plsql2,则会使用TIME字段插入日期。

iv_plsql2 := BEGIN PKG_PRADEEP.P_INSERTDATE(to_date('10-AUG-2012 07:30:30','DD-MM-YYYY HH24:MI:SS'));

有人可以解释为什么会这样吗?

2 个答案:

答案 0 :(得分:0)

我对此的第一个立场是STP P_USER_TIME()正在截断时间戳。但是,如果您确定它可能不这样做,您可以尝试 -

DECLARE
   ret_int INTEGER;
   plsql_block  VARCHAR2(1000);
BEGIN
   plsql_block :='BEGIN P_USER_TIME(to_timestamp(''21-JUL-2012 03:30:30'',''DD-MON-YYYY HH24:MI:SS'')); END;';
   ret_int := DBMS_SQL.OPEN_CURSOR;
   DBMS_SQL.PARSE(ret_int,plsql_block,DBMS_SQL.NATIVE);
   ret_int_execute := DBMS_SQL.EXECUTE(ret_int);
   DBMS_SQL.CLOSE_CURSOR(ret_int);
EXCEPTION
WHEN OTHERS THEN
   DBMS_SQL.CLOSE_CURSOR(ret_int);
END;

注意 - 有许多与ODBC驱动程序相关的与日期时间相关的错误。例如 - 错误11864041 - TIMESTAMP VARIABLE PASSED AS VARCHAR from ODBC CAUSING VALUE TO BE CORRUPT(Oracle Support

答案 1 :(得分:0)

你所说的似乎有些矛盾,但流程并不十分清楚。您有一个从函数(未命名)调用的过程(P_USER_TIME?)。你的程序(至少看看它是如何声明的)会获取一个字符串参数,但是你传递的是date,而不是varchar2值。由于我们没有您的实际程序,让我们提出一个:

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;
/

如果我用plsql_block传递的字符串调用它,我会得到:

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.

所以时间部分丢失了。您正在将表示日期的字符串转换为date对象,并且当它传递给过程时,它会使用您的默认NLS_DATE_FORMAT掩码隐式转换回字符串,我猜这可能是{{1} };所以这相当于:

DD-MON-YYYY

执行exec P_USER_TIME(to_char(to_date('21-JUL-2012 03:30:30','DD-MON-YYYY HH24:MI:SS'))); 看起来多余,但因为你有一个明确的数据掩码而另一个是隐式数据掩码,所以它可能没有达到预期的效果。

假设to_char(to_date(...))过程期望您传递的特定格式的日期/时间字符串,您应该只传递字符串,而不是尝试自己转换它:

P_USER_TIME

您还有一个动态调用过程的函数。再一次,让我们做一个:

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.

所以同样的事情发生了。如果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. 的构造简化为:

plsql_block

然后你得到:

    plsql_block := 'BEGIN P_USER_TIME(''21-JUL-2012 03:30:30''); END;';

再次阅读这个问题,实际上可能是一个更简单的潜在问题。 你说'...字符串参数,我使用to_date函数以字符串格式传递当前日期'。 如果按照字面意思进行解释,则表明您可能只是在Parameter p_time: 21-JUL-2012 03:30:30 Converted l_time: 21-JUL-2012 03:30:30 PL/SQL procedure successfully completed. 时使用to_date; 如果你真的想要当前的时间会使函数中的行像:

to_char

或使用直接调用程序:

 plsql_block := 'BEGIN P_USER_TIME(to_char(sysdate, ''DD-MON-YYYY HH24:MI:SS'')); END;';

编辑以查看作为评论发布的Java代码

你的函数现在似乎有两个参数,其中一个是你想要执行的块;并返回一个游标。我将(再次)猜测光标正在返回已插入的内容,因此我更改了我的虚拟过程以将日期/时间插入到表中,并且我的函数用于检索它。如果你发布了一套完整的代码来证明你所看到的问题,那将会容易得多。

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.

我仍然可以从SQL * Plus中调用它,没有任何问题。我可以让Java程序执行它:

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;
/

这似乎很好;这有三次调用Java程序的输出。

您还没有说出为什么您认为Java代码中的时间被截断的原因。我会更进一步......你是不是把它放在你的Java显示器上,显示为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 ;如果是,您使用的是00:00:00而不是rs.getDate()吗?与rs.getTimestamp不同,java.sql.Date没有时间部分。 (例如,见this question)。