Oracle
 sql >> Base de données >  >> RDS >> Oracle

Pas un mois valide lors de l'exécution d'une procédure de paramètre IN avec une valeur de date

Votre procédure prend des paramètres de type timestamp . Vous passez en fait des paramètres de type varchar2 dans votre appel. Cela oblige Oracle à effectuer une conversion implicite du varchar2 paramètres à timestamp en utilisant le NLS_TIMESTAMP_FORMAT de votre session . Cela sera probablement différent pour différentes sessions, il est donc probable qu'au moins certaines sessions obtiendront une erreur car la chaîne ne correspond pas au format du NLS_TIMESTAMP_FORMAT de cette session. . Vous seriez bien mieux servi en passant un horodatage réel soit en appelant explicitement to_timestamp ou en passant un littéral d'horodatage.

Votre procédure prend alors le timestamp paramètres et transmettez-les au to_date fonction. Le to_date la fonction ne prend pas de paramètres de type timestamp , il ne prend que des paramètres de type varchar2 . Cela oblige Oracle à effectuer une autre conversion implicite du timestamp paramètres à varchar2 , en utilisant à nouveau le NLS_TIMESTAMP_FORMAT de la session . Si le NLS_TIMESTAMP_FORMAT de la session ne correspond pas au masque de format explicite dans votre to_date call, vous obtiendrez une erreur ou la conversion renverra un résultat inattendu.

Si la colonne de votre tableau est en fait de type date , vous pouvez directement comparer une date à un timestamp . Il ne semble donc pas y avoir de raison d'appeler to_date ici. Cependant, sur la base de vos exemples de données, il semble que la colonne de votre tableau soit en fait de type timestamp plutôt que date comme votre code l'indique, puisqu'une date n'a pas de fraction de seconde de précision. Si tel est le cas, il est encore moins logique d'appeler to_date dans votre SELECT car vos paramètres sont en fait de type timestamp et votre colonne est de type timestamp . Comparez simplement l'timestamp valeurs.

Je suppose donc que vous voulez quelque chose comme

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;

et que vous souhaitez caler la procédure en transmettant des horodatages réels. Utilisation de littéraux d'horodatage

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

ou en appelant explicitement 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' ) );

Cela devrait éliminer toutes les conversions de type implicites en cours.