Oracle
 sql >> Datenbank >  >> RDS >> Oracle

Kein gültiger Monat beim Ausführen einer IN-Parameterprozedur mit Datumswert

Ihre Prozedur verwendet Parameter vom Typ timestamp . Sie übergeben tatsächlich Parameter vom Typ varchar2 in deinem Anruf. Dadurch wird Oracle gezwungen, eine implizite Konvertierung von varchar2 durchzuführen Parameter zu timestamp unter Verwendung des NLS_TIMESTAMP_FORMAT Ihrer Sitzung . Dies wird wahrscheinlich für verschiedene Sitzungen unterschiedlich sein, daher ist es wahrscheinlich, dass zumindest einige Sitzungen einen Fehler erhalten, weil die Zeichenfolge nicht mit dem Format von NLS_TIMESTAMP_FORMAT dieser Sitzung übereinstimmt . Es wäre viel besser, einen tatsächlichen Zeitstempel zu übergeben, indem Sie entweder explizit to_timestamp aufrufen oder durch Übergeben eines Zeitstempel-Literals.

Ihre Prozedur übernimmt dann den timestamp Parameter und übergebe sie an to_date Funktion. Der to_date Die Funktion akzeptiert keine Parameter vom Typ timestamp , es werden nur Parameter vom Typ varchar2 verwendet . Das zwingt Oracle zu einer weiteren impliziten Konvertierung des timestamp Parameter zu varchar2 , wiederum unter Verwendung des NLS_TIMESTAMP_FORMAT der Sitzung . Wenn das NLS_TIMESTAMP_FORMAT der Sitzung stimmt nicht mit der expliziten Formatmaske in Ihrem to_date überein aufrufen, erhalten Sie einen Fehler oder die Konvertierung gibt ein Ergebnis zurück, das Sie nicht erwarten.

Wenn die Spalte in Ihrer Tabelle tatsächlich vom Typ date ist , können Sie ein date direkt vergleichen zu einem timestamp . Es scheint also keinen Grund zu geben, to_date aufzurufen hier. Basierend auf Ihren Beispieldaten scheint es jedoch, dass die Spalte in Ihrer Tabelle tatsächlich vom Typ timestamp ist statt date wie Ihr Code andeutet, seit einem date hat keine Sekundenbruchteilgenauigkeit. Wenn das der Fall ist, macht es noch weniger Sinn, to_date aufzurufen in Ihrem SELECT -Anweisung, da Ihre Parameter eigentlich vom Typ timestamp sind und Ihre Spalte ist vom Typ timestamp . Vergleichen Sie einfach den timestamp Werte.

Meine Vermutung ist daher, dass Sie so etwas wie

wollen
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;

und dass Sie die Prozedur aufrufen möchten, indem Sie tatsächliche Zeitstempel übergeben. Verwenden von Zeitstempelliteralen

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

oder durch explizites Aufrufen von 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' ) );

Das sollte alle impliziten Typkonvertierungen beseitigen, die derzeit stattfinden.