我正在尝试使用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'));
有人可以解释为什么会这样吗?
答案 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)。