您所说的似乎有些矛盾,但流程不是很清楚。您有一个从函数(未命名)调用的过程 (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_char;
如果您真的想要使函数中的行类似于以下内容的当前时间:
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.sql.Date 没有时间部分,与 java.util.Date 不同。 (例如参见this question)。