あなたの言っていることは矛盾しているように見えますが、その流れはあまり明確ではありません。関数 (名前なし) から呼び出されるプロシージャ ( 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.
プロシージャを動的に呼び出す関数もあります。もう一度、1 つを作成しましょう。
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コードを見るように編集
関数は 2 つの引数を取るようになりました。そのうちの 1 つは実行するブロックです。カーソルを返します。カーソルが挿入されたものを返すと (再び) 推測するので、日付/時刻をテーブルに挿入するようにダミー プロシージャを変更し、それを取得する関数を変更しました。もちろん、発生している問題を示す完全なコード セットを投稿すると、これはずっと簡単になります。
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 プログラムへの 3 回の呼び出しからの出力です。
Java コードで時間が切り捨てられていると考える理由については、まだ詳しく説明していません。私は手足をさらに詳しく説明します... Javaのディスプレイに基づいて、それを次のように表示していますか00:00:00
?もしそうなら、rs.getDate()
代わりに使用していますrs.getTimestamp
か?java.sql.Date
とは異なり、 には時間部分がありませんjava.util.Date
。(たとえば、この質問を参照してください)。