sql >> Base de Datos >  >> RDS >> Oracle

No es un mes válido al ejecutar un procedimiento de parámetro IN con valor de fecha

Su procedimiento toma parámetros de tipo timestamp . En realidad, está pasando parámetros de tipo varchar2 en tu llamada. Eso obliga a Oracle a realizar una conversión implícita de varchar2 parámetros a timestamp utilizando el NLS_TIMESTAMP_FORMAT de su sesión . Es probable que sea diferente para diferentes sesiones, por lo que es probable que al menos algunas sesiones reciban un error porque la cadena no coincide con el formato del NLS_TIMESTAMP_FORMAT de esa sesión. . Sería mucho mejor pasar una marca de tiempo real llamando explícitamente a to_timestamp o pasando un literal de marca de tiempo.

Su procedimiento luego toma la timestamp parámetros y pasarlos a to_date función. El to_date la función no toma parámetros de tipo timestamp , solo toma parámetros de tipo varchar2 . Eso obliga a Oracle a realizar otra conversión implícita de timestamp parámetros a varchar2 , nuevamente usando el NLS_TIMESTAMP_FORMAT de la sesión . Si la sesión NLS_TIMESTAMP_FORMAT no coincide con la máscara de formato explícito en su to_date llamada, obtendrá un error o la conversión arrojará un resultado que no esperaba.

Si la columna de su tabla es en realidad del tipo date , puedes comparar directamente una date a una timestamp . Así que no parece haber ninguna razón para llamar a to_date aquí. Sin embargo, según sus datos de muestra, parece que la columna en su tabla es en realidad del tipo timestamp en lugar de date como implica su código, desde una date no tiene fracciones de segundo de precisión. Si ese es el caso, tiene aún menos sentido llamar a to_date en tu SELECT declaración ya que sus parámetros son en realidad del tipo timestamp y su columna es del tipo timestamp . Simplemente compare la timestamp valores.

Mi conjetura, por lo tanto, es que quieres algo como

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;

y que desea llamar al procedimiento pasando las marcas de tiempo reales. Usar literales de marca de tiempo

Execute proc1(timestamp '2014-05-05 11:25:00', timestamp '2014-05-05 12:25:00' )

o llamando explícitamente a 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' ) );

Eso debería eliminar todas las conversiones de tipos implícitas que se están produciendo actualmente.