Oracle
 sql >> Base de Dados >  >> RDS >> Oracle

Não é um mês válido ao executar um procedimento de parâmetro IN com valor de data


Seu procedimento recebe parâmetros do tipo timestamp . Na verdade, você está passando parâmetros do tipo varchar2 em sua chamada. Isso força o Oracle a realizar a conversão implícita do varchar2 parâmetros para timestamp usando o NLS_TIMESTAMP_FORMAT da sua sessão . Isso provavelmente será diferente para sessões diferentes, portanto, é provável que pelo menos algumas sessões recebam um erro porque a string não corresponde ao formato do NLS_TIMESTAMP_FORMAT dessa sessão . Você seria muito mais bem servido passando um timestamp real chamando explicitamente to_timestamp ou passando um literal de carimbo de data/hora.

Seu procedimento então pega o timestamp parâmetros e passá-los para o to_date função. O to_date a função não recebe parâmetros do tipo timestamp , leva apenas parâmetros do tipo varchar2 . Isso força o Oracle a fazer outra conversão implícita do timestamp parâmetros para varchar2 , novamente usando o NLS_TIMESTAMP_FORMAT da sessão . Se o NLS_TIMESTAMP_FORMAT da sessão não corresponde à máscara de formato explícito em seu to_date chamada, você receberá um erro ou a conversão retornará um resultado que você não espera.

Se a coluna em sua tabela for realmente do tipo date , você pode comparar diretamente uma date para um timestamp . Portanto, não parece haver nenhum motivo para chamar to_date aqui. No entanto, com base em seus dados de exemplo, parece que a coluna em sua tabela é realmente do tipo timestamp em vez de date como seu código indica, uma vez que uma date não possui segundos fracionários de precisão. Se for esse o caso, faz ainda menos sentido chamar to_date em seu SELECT já que seus parâmetros são realmente do tipo timestamp e sua coluna é do tipo timestamp . Basta comparar o timestamp valores.

Meu palpite, portanto, é que você quer 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;

e que você deseja chamar o procedimento passando os timestamps reais. Usando literais de carimbo de data/hora
Execute proc1(timestamp '2014-05-05 11:25:00', timestamp '2014-05-05 12:25:00' )

ou chamando explicitamente 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' ) );

Isso deve eliminar todas as conversões de tipo implícitas que estão ocorrendo no momento.