Oracle
 sql >> Baza danych >  >> RDS >> Oracle

Niepoprawny miesiąc podczas wykonywania procedury parametru IN z wartością daty

Twoja procedura przyjmuje parametry typu timestamp . W rzeczywistości przekazujesz parametry typu varchar2 w Twojej rozmowie. To zmusza Oracle do przeprowadzenia niejawnej konwersji varchar2 parametry do timestamp przy użyciu NLS_TIMESTAMP_FORMAT sesji . Prawdopodobnie będzie to różne dla różnych sesji, więc jest prawdopodobne, że przynajmniej niektóre sesje otrzymają błąd, ponieważ ciąg nie pasuje do formatu NLS_TIMESTAMP_FORMAT tej sesji . Będziesz znacznie lepiej obsługiwany, przekazując w rzeczywistym znaczniku czasu, albo jawnie wywołując to_timestamp lub przekazując literał znacznika czasu.

Twoja procedura następnie pobiera timestamp parametry i przekaż je do to_date funkcjonować. to_date funkcja nie przyjmuje parametrów typu timestamp , przyjmuje tylko parametry typu varchar2 . To zmusza Oracle do wykonania kolejnej niejawnej konwersji timestamp parametry do varchar2 , ponownie używając NLS_TIMESTAMP_FORMAT sesji . Jeśli NLS_TIMESTAMP_FORMAT sesji nie pasuje do jawnej maski formatu w Twoim to_date wywołanie, pojawi się błąd lub konwersja zwróci wynik, którego nie oczekujesz.

Jeśli kolumna w Twojej tabeli faktycznie ma typ date , możesz bezpośrednio porównać date do timestamp . Wygląda więc na to, że nie ma żadnego powodu, aby wywoływać to_date tutaj. Jednak na podstawie przykładowych danych wygląda na to, że kolumna w tabeli ma w rzeczywistości typ timestamp zamiast date jak sugeruje twój kod, ponieważ date nie ma precyzji ułamków sekund. W takim przypadku wywoływanie to_date ma jeszcze mniej sensu w swoim SELECT oświadczenie, ponieważ twoje parametry są w rzeczywistości typu timestamp a Twoja kolumna ma typ timestamp . Wystarczy porównać timestamp wartości.

Domyślam się zatem, że chcesz czegoś takiego

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;

i chcesz wywołać procedurę, przekazując rzeczywiste znaczniki czasu. Korzystanie z literałów znaczników czasu

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

lub jawnie wywołując 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' ) );

Powinno to pozbyć się wszystkich niejawnych konwersji typów, które obecnie mają miejsce.




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Jak udokumentować bazę danych

  2. PLS-00428:w tej instrukcji SELECT oczekiwana jest klauzula INTO

  3. Usuń losowe wyrażenie z ciągu

  4. jak używać kaskady w Oracle

  5. dodawanie dni roboczych w Oracle sql