Witaj Gościu! ( Zaloguj | Rejestruj )

Forum PHP.pl

 
Reply to this topicStart new topic
> [PostgreSQL] Problem z funkcją przed update
KcR
post 21.06.2014, 11:38:36
Post #1





Grupa: Zarejestrowani
Postów: 4
Pomógł: 0
Dołączył: 8.06.2014

Ostrzeżenie: (0%)
-----


Cześć wszystkim,

Mam problem z funkcją, która sprawdza kwotę kary pieniężnej za przetrzymaną książkę i wpisuje ją do odpowiedniej kolumny. Problem jest taki, że próbowałem na różne sposoby zmienić tą funkcję, a problem wyskakuje wciąż ten sam. Ostatnia aktualizacja błędu wraz z kodem funkcji poniżej:

KOD FUNKCJI:
  1. CREATE OR REPLACE FUNCTION policz_pieniadze() RETURNS TRIGGER AS'
  2. DECLARE
  3. roznica_dat int4;
  4. data_zwrotu date;
  5. data_przewidywana date;
  6.  
  7. BEGIN
  8. SELECT borrowed_books.date_due_for_return INTO data_przewidywana FROM borrowed_books WHERE book_borrowing_id = OLD.book_borrowing_id;
  9. data_zwrotu = NEW.date_returned;
  10. roznica_dat = data_zwrotu - data_przewidywana;
  11. IF roznica_dat > 0 THEN
  12. UPDATE borrowed_books SET amount_of_fine = roznica_dat * (SELECT value FROM rules WHERE rules_id = 1) WHERE borrowed_books.book_borrowing_id = OLD.book_borrowing_id;
  13. RETURN NEW;
  14. ELSE
  15. UPDATE borrowed_books SET amount_of_fine = 0 WHERE borrowed_books.book_borrowing_id = OLD.book_borrowing_id;
  16. RETURN NEW;
  17. END IF;
  18. END;
  19. 'LANGUAGE 'plpgsql';


KOD BŁĘDU:
ERROR: stack depth limit exceeded
HINT: Increase the configuration parameter "max_stack_depth".
CONTEXT: SQL statement "SELECT 1 FROM ONLY "public"."books" x WHERE "isbn" = $1 FOR SHARE OF x"
SQL statement "UPDATE borrowed_books SET amount_of_fine = $1 * (SELECT value FROM rules WHERE rules_id = 1) WHERE borrowed_books.book_borrowing_id = $2 "

Z góry dziękuję za pomoc.
Go to the top of the page
+Quote Post
Crozin
post 21.06.2014, 11:51:20
Post #2





Grupa: Zarejestrowani
Postów: 6 474
Pomógł: 1306
Dołączył: 6.08.2006
Skąd: Kraków

Ostrzeżenie: (0%)
-----


Czy mi się wydaje czy w tym triggerze odpalasz zawsze zapytanie UPDATE na tej samej tabeli co skutkuje zapętleniem całości? Zamiast wykonywać zapytania UPDATE po prostu zmień wartość rekordu z NEW:
  1. IF roznica_data > 0 THEN
  2. NEW.amount_of_fine := ...;
  3. ELSE
  4. NEW.amount_of_fine := 0;
  5. END IF;
  6.  
  7. RETURN NEW;
Go to the top of the page
+Quote Post
KcR
post 21.06.2014, 12:46:54
Post #3





Grupa: Zarejestrowani
Postów: 4
Pomógł: 0
Dołączył: 8.06.2014

Ostrzeżenie: (0%)
-----


Czyli jeśli w triggerze występuje Update to znowu "załącza się" ten sam trigger i tak w kółko? A więc tak działa rekurencja w PSQL oneeyedsmiley02.png Ok, w takim razie funkcja jest trochę odchudzona, lecz w tym problem że nie chce się zapisać kwota kary do tabeli (Nie wiem jak, ale sposób NEW.amount_of_fine = ... nie działa). Może mi ktoś wytłumaczyć jak to zrobić? Próbowałem rzutować, kombinować ze zmiennymi roznica_dat i (SELECT value ...) ale raczej nie tutaj jest problem.

FUNKCJA PO ODCHUDZENIU:
  1. CREATE OR REPLACE FUNCTION policz_pieniadze() RETURNS TRIGGER AS'
  2. DECLARE
  3. roznica_dat int;
  4. BEGIN
  5. roznica_dat = NEW.date_returned - OLD.date_due_for_return;
  6. IF roznica_dat > 0 THEN
  7. NEW.amount_of_fine = roznica_dat * (SELECT value FROM rules WHERE rules_id = 1);
  8. ELSE
  9. NEW.amount_of_fine = 0;
  10. END IF;
  11. RETURN NEW;
  12. END;
  13. 'LANGUAGE 'plpgsql';


EDIT:
Jeśli to potrzebne to kolumna amount_of_fine jest typu real, i select też wyrzuca typ real.
Wpadłem jeszcze na pomysł, aby po prostu usunąć ten wiersz w którym zachodzi update i wstawić go na nowo, ale sądzę iż ktoś zna lepszy sposób na to.

EDIT2:
Ok, problem tkwił w ustawieniu triggera, który musi być before update zamiast after update (wtedy zadziałało, choć byłoby miło jakby ktoś mi wytłumaczył dlaczego). Dziękuję za pomoc Crozin smile.gif.

Ten post edytował KcR 21.06.2014, 13:03:00
Go to the top of the page
+Quote Post
Crozin
post 21.06.2014, 12:57:25
Post #4





Grupa: Zarejestrowani
Postów: 6 474
Pomógł: 1306
Dołączył: 6.08.2006
Skąd: Kraków

Ostrzeżenie: (0%)
-----


= to operator porównania, := to operator przypisania.
Go to the top of the page
+Quote Post

Reply to this topicStart new topic
1 Użytkowników czyta ten temat (1 Gości i 0 Anonimowych użytkowników)
0 Zarejestrowanych:

 



RSS Wersja Lo-Fi Aktualny czas: 17.11.2018 - 06:14