Reputation: 353
CREATE OR REPLACE PROCEDURE PROC1(
V_STARTTIME IN TIMESTAMP ,
V_ENDTIME IN TIMESTAMP )
BEGIN
INSERT INTO TAB1
SELECT COINS FROM TAB2
WHERE DATE BETWEEN TO_DATE(V_STARTTIME,'mm/dd/yyyy hh:mi:ss aM') AND TO_DATE(V_ENDTIME ,'mm/dd/yyyy hh:mi:ss aM');
END;
SAMPLE DATE in Tab2 5/5/2014 9:46:38.000000 AM
My script runs between a range of dates. The two dates are IN parameters.
When I execute the procedure
Execute proc1('5/05/2014 11:25:00 AM','5/05/2014 12:25:00 PM')
I am getting not a valid month error. Any idea how to fix this? Thanks
Upvotes: 0
Views: 2821
Reputation: 231711
Your procedure takes parameters of type timestamp
. You're actually passing parameters of type varchar2
in your call. That forces Oracle to perform implicit conversion of the varchar2
parameters to timestamp
using your session's NLS_TIMESTAMP_FORMAT
. That will likely be different for different sessions so it is likely that at least some sessions will get an error because the string doesn't match the format of that session's NLS_TIMESTAMP_FORMAT
. You'd be much better served passing in an actual timestamp either by explicitly calling to_timestamp
or by passing a timestamp literal.
Your procedure then takes the timestamp
parameters and pass them to the to_date
function. The to_date
function does not take parameters of type timestamp
, it only takes parameters of type varchar2
. That forces Oracle to do another implicit conversion of the timestamp
parameters to varchar2
, again using the session's NLS_TIMESTAMP_FORMAT
. If the session's NLS_TIMESTAMP_FORMAT
doesn't match the explicit format mask in your to_date
call, you'll get an error or the conversion will return a result that you don't expect.
If the column in your table is actually of type date
, you can directly compare a date
to a timestamp
. So there doesn't appear to be any reason to call to_date
here. Based on your sample data, though, it appears that the column in your table is actually of type timestamp
rather than date
as your code implies, since a date
does not have fractional seconds of precision. If that's the case, it makes even less sense to call to_date
in your SELECT
statement since your parameters are actually of type timestamp
and your column is of type timestamp
. Just compare the timestamp
values.
My guess, therefore, is that you want something like
CREATE OR REPLACE PROCEDURE PROC1(
V_STARTTIME IN TIMESTAMP ,
V_ENDTIME IN TIMESTAMP )
BEGIN
INSERT INTO TAB1( <<column name>> )
SELECT COINS
FROM TAB2
WHERE <<timestamp column name>> BETWEEN v_starttime AND v_endtime;
END;
and that you want to cal the procedure by passing actual timestamps. Using timestamp literals
Execute proc1(timestamp '2014-05-05 11:25:00', timestamp '2014-05-05 12:25:00' )
or by explicitly calling to_timestamp
execute proc1( to_timestamp( '5/05/2014 11:25:00 AM', 'MM/DD/YYYY HH:MI:SS AM' ),
to_timestamp( '5/05/2014 12:25:00 PM', 'MM/DD/YYYY HH:MI:SS AM' ) );
That should get rid of all the implicit type conversions that are currently taking place.
Upvotes: 2