Funkcja zwracająca najwyższą datę,PL/SQL

0

Witam
Mam problem z funkcją

CREATE OR REPLACE FUNCTION 002.GET_YEAR (P_DATE IN DATE) 
    RETURN VARCHAR2 
  IS 
  DECLARE
v_Date VARCHAR2;
  BEGIN
 select to_char(MAX(to_date(actual_date,'YYYY-MM-DD')),'YYYYMMDD') as ACTUAL_DATE
   INTO v_Date FROM (select distinct actual_date from MXI3_T_TRADES_RAW);
    IF P_DATE IS NULL THEN
      RETURN NULL;
     ELSIF v_Date > P_DATE THEN
      TO_CHAR(v_DATE, 'YYYYMMDD');
    ELSE
     TO_CHAR(P_DATE, 'YYYYMMDD');
   END IF;
  END GET_YEAR;

Dostaje błąd:
PLS-00103: Encountered the symbol "DECLARE" when expecting one of the following:

begin function pragma procedure subtype type <an identifier="identifier">
current cursor delete
exists prior external language
The symbol "begin" was substituted for "DECLARE" to continue.
Compile error at line 4, column 3
PLS-00103: Encountered the symbol "end-of-file" when expecting one of the following:
;
Compile error at line 16, column 24

0
  1. Wywal to DECLARE, to jest funkcja, a nie blok anonimowy.
  2. Nie zwracasz żadnej wartości w tej funkcji (brak RETURN costam;)
  3. Nazwa funkcji 002.GET_YEAR ?
  4. Możesz to załatwić jednym selectem.
0

Wywałiłem declare i dodałem return

CREATE OR REPLACE FUNCTION 002.GET_YEAR (P_DATE IN DATE) 
     RETURN VARCHAR2 
   IS 
 v_Date VARCHAR2;
   BEGIN
  select to_char(MAX(to_date(actual_date,'YYYY-MM-DD')),'YYYYMMDD') as ACTUAL_DATE
   INTO v_Date FROM (select distinct actual_date from MXI3_T_TRADES_RAW);
     IF P_DATE IS NULL THEN
       RETURN NULL;
      ELSIF v_Date > P_DATE THEN
       P_DATE:=TO_CHAR(v_DATE, 'YYYYMMDD');
    ELSE
      TO_CHAR(P_DATE, 'YYYYMMDD');
    END IF;
  RETURN P_DATE;
   END;

teraz dostaje błąd

0

Ciężko powiedzieć co tam ponaprawiałeś nie widząc kolejnego błędu ;-)

Może po prostu zapytanie z GREATEST? A jak się uprzesz na funkcję to kombinuj w ten sposób.

CREATE OR REPLACE FUNCTION GET_YEAR(P_DATE IN DATE) RETURN VARCHAR2 AS
  V_DATE DATE;
BEGIN
  FOR R IN (SELECT GREATEST(MAX(TO_DATE(ACTUAL_DATE, 'YYYY-MM-DD')), P_DATE)  MAX_DATE FROM MXI3_T_TRADES_RAW) LOOP
    V_DATE := R.MAX_DATE;
  END LOOP; 

  RETURN TO_CHAR(V_DATE,'YYYYMMDD');
END GET_YEAR;
/

Nie mam bazy pod ręką, żeby to zweryfikować.

0

Kod jest taki sam jak we wczesniejszej odpowiedzi czyli:

CREATE OR REPLACE FUNCTION 002.GET_YEAR (P_DATE IN DATE) 
     RETURN VARCHAR2 
   IS 
 v_Date VARCHAR2;
   BEGIN
  select to_char(MAX(to_date(actual_date,'YYYY-MM-DD')),'YYYYMMDD') as ACTUAL_DATE
   INTO v_Date FROM (select distinct actual_date from MXI3_T_TRADES_RAW);
     IF P_DATE IS NULL THEN
       RETURN NULL;
      ELSIF v_Date > P_DATE THEN
       P_DATE:=TO_CHAR(v_DATE, 'YYYYMMDD');
    ELSE
      TO_CHAR(P_DATE, 'YYYYMMDD');
    END IF;
  RETURN P_DATE;
   END;

Błąd w załaczniku

0

Funkcja jest ok, sprawdziłem i działa.

Obstawiam, że instalujesz z jakiegoś dziwnego klienta i wychodzi qpa. Pewnie klient nie rozumie separatora / i tyle. Poszukaj w ustawieniach tego klienta czy da się zmienić separator dla poszcególnych bloków.

0

Dziwna akcja faktycznie odpaliłem SQL Devloper i poszła ta Twoja wersja i takze ta moja, ostatecznie kod wygladał tak:

    create or replace FUNCTION GET_YEAR(P_DATE IN DATE) 
RETURN VARCHAR2 
IS
v_Date1 date;
v_Date VARCHAR2(20);
BEGIN
 select to_date(to_char(MAX(to_date(actual_date,'YYYY-MM-DD')),'YYYYMMDD'),'YYYYMMDD') 
   INTO v_Date1 FROM (select distinct actual_date from MXI3_T_TRADES_RAW);
      IF P_DATE IS NULL THEN
      RETURN NULL;
     ELSIF v_Date1 > P_DATE THEN
      v_Date := TO_CHAR(v_DATE1, 'YYYYMMDD');
    ELSE
    v_Date := TO_CHAR(P_DATE, 'YYYYMMDD');
    END IF;
 RETURN v_DATE;
  END;

Dzieki za pomoc!

0

To jeszcze powiedz co ta funkcja robić. Bo ja tu widzę sporo problemów.

  1. Po co te wielokrotne konwersje TO_DATE, TO_CHAR? Zakładam, że w tabeli masz DATE, wiec po co ją konwertujesz trzy razy?
  2. Z tego co widzę, szukasz maksymalnej daty, ale po co w dwóch krokach?
    Jak dla mnie to zapytanie zrobi to samo:
select max(actual_date) from MXI3_T_TRADES_RAW;
  1. Funkcja to GET_YEAR, a wynik jest zwykłą datą. Na pewno o to chodziło?
0
  1. W RAW dane są przechowywane jako string 500, poniewaz są jeszcze przed walidacją. Niestety te konwersje muszą tam być bo w zrodle mam format YYYY-MM-DD i jest to varchar2 (500).(Taka mamy architekture w WH)
  2. Jeden załadunek do tabeli to jest prawie milion rekordow(z czego będą tylko dwie rozne daty), dlatego wyciagnałem sobie distincta, zeby zwrocił mi maxa z przefiltorwanych danych.
  3. to tylko nazwa tutaj na forum, nie chciałem kopiowac bezposrednio.
1

No dobrze, ale te dwie zewnętrzne konwersje są zbędne, wystarczy: MAX(to_date(actual_date,'YYYY-MM-DD')).
Nie staraj się robić czegoś za bazę - zrób od razu max na danych, bez żadnego distincta. Jakby się uprzeć, to zamiast tych IFów można zrobić CASE, który od razu zwróci wynik tej funkcji.
I czy na pewno musisz zwracać datę w postaci tekstowej? Wtedy format daty jest gdzieś zaszyty w funkcji i na zewnątrz nie jest znany. Jeśli inaczej nie możesz, to w pakiecie z tą funkcją zrób stałą globalną z formatem daty, żeby wywołujący funkcję mógł sobie zrobić konwersję tego tekstu na datę.

1 użytkowników online, w tym zalogowanych: 0, gości: 1