TO_DATE Oracle DBMS_SQL.EXECUTE函数问题

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

用于调用函数的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将它传递给另一个过程。我可以看到过去与日期相关的时间没有插入到某个场景中。 请在下面找到我的function

 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 AM 

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

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

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

我对此的第一个立场是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来自ODBC导致值被破坏( Oracle支持 )

你所说的似乎有一个矛盾,但流程并不十分清楚。 你有一个从函数(未命名)调用的过程( 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掩码隐式转换回字符串,我猜这可能是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;'; 

然后你得到:

 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_date时使用to_date ; 如果你真的想要当前时间会使函数中的行像:

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

或者使用直接调用程序:

 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. 

编辑以查看作为评论发布的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; / 

我仍然可以从SQL * Plus中调用它,没有任何问题。 我可以让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 

这看起来很好; 这有三次调用Java程序的输出。

您还没有说出为什么您认为Java代码中的时间被截断的原因。 我会更进一步……你是把它放在显示器上,从你的Java显示为00:00:00 ; 如果是这样,你使用rs.getDate()而不是rs.getTimestamp吗? 与java.util.Date不同, java.sql.Date没有时间部分。 (例如,请参阅此问题 )。