Wyniki procedury zwracają błędne dane

Wyniki procedury zwracają błędne dane
BL
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 95
0

Witam.

Jestem początkujący w pisaniu procedur. Napisałem procedurę która zwraca mi dane na podstawie zakresów dat. Wartości obrotu pokazują jednak zera mimo że prawdziwy obrót jest zdecydowanie wyższy. Nie do końca jednak wiem co zrobiłem źle. Stąd moja prośba o pomoc.

Moja procedura :

Kopiuj
create or replace PROCEDURE Marza_II_PROCEDURE(FirstDateOpen DATE,FirstDateClose DATE
,SecondDateOpen DATE ,SecondDateClose DATE
)
as

BEGIN
Begin
EXECUTE IMMEDIATE 'DROP TABLE MARZA_REPORT' ;
EXCEPTION
   WHEN OTHERS THEN
      IF SQLCODE != -942 THEN
         RAISE;
      END IF;
    End;
    COMMIT;
EXECUTE IMMEDIATE 'CREATE TABLE MARZA_REPORT AS
    select BH,ODBIORCA,KANAL_SPRZEDAZY,SEGMENT2018,SEGMENT2019,
SUM(CASE WHEN MIESIAC BETWEEN '|| FirstDateOpen ||' and '||FirstDateClose ||' then OBROT else 0 end) OBROT1,
SUM(CASE WHEN MIESIAC BETWEEN '|| SecondDateOpen ||' and '||SecondDateClose ||' then OBROT else 0 end) OBROT2
from dws1.marza_netto

WHERE MIESIAC >= '|| SecondDateOpen ||' 
AND ODBIORCA IN (''0001006834'',''0001024402'',''0001000043'')
GROUP BY BH,ODBIORCA,KANAL_SPRZEDAZY,SEGMENT2018,SEGMENT2019';

END;

Wywołuję to :

Kopiuj
Begin
Marza_II_PROCEDURE(to_date('20190101','yyyymmdd'),to_date('20190201','yyyymmdd'),to_date('20180101','yyyymmdd'),to_date('20180201','yyyymmdd'));
End;

Jednak dane które są zwracane do tablicy są błędne.

YA
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 2386
0

W tej Twojej procedurze:

  • COMMIT; po DROP jest niepotrzebny, bo w Oracle DDLe powodują niejawnego commita (wiąże się to z zatwierdzeniem zmian w słowniku systemowym)
  • Zamiast kleić te zapytanie i ginąć w nadmiarze ', można użyć techniki "escape single quote":
Kopiuj
v_statement := q'[  select 1 from dual where 'a'='a' ]';
  • Zamiast doklejać wartości użyj zmiennych w zapytaniu i przekaż wartości:
Kopiuj
v_statement := q'[ select 1 from dual where 1=:jeden and 2=:dwa ]'
EXECUTE IMMEDIATE v_statement USING v_value_a, v_value_b; 
  • WHERE MIESIAC >= '|| SecondDateOpen ||' , nie wiem co siedzi w kolumnie MIESIAC, ale nazwa wskazuje, że miesiąc, a nie jakaś data. Przekazujesz to_date('20180101','yyyymmdd').
abrakadaber
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 6610
0

a ja mam pytanie dlaczego w ogóle używasz EXECUTE IMMEDIATE?

R7
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 216
0
  1. Unikamy tworzenia/usuwania obiektów wewnątrz procedur - możesz zrobić zwykły DELETE
    albo ewentualnie TRUNCATE, jeśli zawartość tabeli jest bardzo duża

  2. Błąd zapewne polega na porównywaniu pola MIESIAC z datą, co z tego wyjdzie to trudno powiedzieć.
    Pokaż jak wygląda definicja tabeli i przykładowe wartości tego pola - czy jest to np. 11 czy też 201811?
    Albo '2018-11'?

Poza tym w SUM masz ten sam problem:

CASE WHEN MIESIAC BETWEEN '|| FirstDateOpen ||' and '||FirstDateClose ||' then OBROT else 0 end

Tak jak w matematyce, musisz to sprowadzić do wspólnego mianownika. Musisz porównywać pola o tych samych typach,
czyli albo MIESIAC konwertujesz na datę albo daty przerabiasz tak, żeby pasowały do formatu pola MIESIAC.

  1. Dynamiczny SQL jest tu zbędny - zamień CREATE TABLE na INSERT ... SELECT ...

Zarejestruj się i dołącz do największej społeczności programistów w Polsce.

Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.