Oracle SQLDeveloper Trigger

0

Cześć wszystkim.
Mam następujący problem, stworzyłem trigger, który wypełnia ID za pomocą zwykłej sekwencji oraz losuje 3 kolejne wartości kolumn jako wartości liczbowe (2 pierwsze to ID innych tabel, trzecia to ilość). Dorzuciłem tam selecta, który sprawdza, czy te dwie wylosowane wartości już wcześniej nie wystąpiły. Jeśli nie, to wszystko dobrze i tworzy nowy wiersz z tymi wartościami. A jeśli powtórzył się, to chciałbym, aby ten wiersz nie tworzył się tylko dodał do wcześniej stworzonego tę trzecią wartość liczbową. Niestety brakuje mi pomysłu.

0

Wrzucam jeszcze kod w razie czego

create or replace TRIGGER TR_EGZEMPLARZ BEFORE INSERT ON EGZEMPLARZ_FILMU
FOR EACH ROW

DECLARE 
LpFilmow NUMBER;                --Ilosc filmów z tabeli Film
LpTypowWydania NUMBER;          --Ilosc typów wydania z tabeli Typ_wydania
flag NUMBER default 0;          --flaga przyjmuje wartosc ID_Ef jesli film i wydanie są powtórzone
idfilmu NUMBER default 0;       --losowanie filmu
idtypuwydania NUMBER default 0; --losowanie typu wydania
LpE NUMBER default 0;           --wylosowana ilosc dostepnych egzemplarzy
OldValue NUMBER default 0;      --stara ilosc
maks NUMBER default 0;          --maksymalna wartosc ID_Ef

BEGIN
  SELECT COUNT(ID_F) INTO LpFilmow FROM Film;               --sprawdza ilosc dostepnych filmow
  SELECT COUNT(ID_Tw) INTO LpTypowWydania FROM Typ_wydania; --sprawdza ilosc dostepnych typow wydania
  idfilmu := dbms_random.value(1, LpFilmow); 
  idtypuwydania := dbms_random.value(1, LpTypowWydania); --teraz idfilmu i idtypuwydania losują tylko istniejące wartości w innych tabelach
  SELECT ID_Ef INTO flag FROM Egzemplarz_filmu WHERE ID_F = idfilmu and ID_Tw = idtypuwydania; --sprawdzenie powtórzenia
  
  IF flag = 0
  THEN--tutaj trigger wykonuje sie jesli nowa wartosc jest unikalna
  :new.ID_F := idfilmu;
  :new.ID_Tw := idtypuwydania;
  :new.Ilosc_dostepnych := dbms_random.value(10,100);

  ELSE --wykonanie triggera dla powtorzonej wartosci
  :new.ID_F := idfilmu;
  :new.ID_Tw := idtypuwydania;
  LpE := dbms_random.value(10,100); 
  :new.Ilosc_dostepnych := LpE;
  
  SELECT Ilosc_dostepnych INTO OldValue FROM Egzemplarz_filmu WHERE ID_Ef = flag;
  OldValue := OldValue + LpE;
  UPDATE Egzemplarz_filmu SET Ilosc_dostepnych = OldValue WHERE ID_EF = flag;
  SELECT MAX (ID_Ef) INTO maks FROM Egzemplarz_filmu;
  DELETE Egzemplarz_filmu where ID_Ef = maks;
  END IF;
  
END;
```plsql
0

nie da się tego zrobić triggerem - jedyny sposób aby "zablokować" wstawienie rekordu w triggerze to rzucić wyjątkiem a to już trzeba obsłużyć po stronie klienta. Reasumując - można wylosować losowe wartości IDków i je wstawić, można zwiększyć wartość komórki w całkiem innym rekordzie ale nie można nie stawić rekordu "po cichu"

0

A tworząc drugi trigger, który usuwa powielony wiersz?

2

nie możesz modyfikować w triggerze rekordu, na rzecz którego ten trigger jest wywoływany

To w jaki sposób chcesz to osiągnąć jest nielogiczne.

0
Fafkorn napisał(a):

A tworząc drugi trigger, który usuwa powielony wiersz?

W teorii można tak zrobić ale nie jest to zbyt eleganckie rozwiązanie. Ponadto w przypadku takiej "logiki triggerowej" dopiero bodajże od wersji 11 oracle można sterować kolejnością wykonywania triggerów. We wcześniejszych wersjach jak miałeś np dwa triggery after insert to nie miałeś wpływu na to który odpali się jako pierwszy.

0

Użyj klauzuli MERGE INTO ..
USING
SELECT..
WHEN MATCHED THEN
UPDATE ..
WHEN NOT MATCHED THEN
INSERT..

można też zalozyć unique constraint na te kolumny i obsłużyć ten wyjątek w exception ale żeby to zrobić to w trigerze byś musiał wywowałć prodecedure zewnetrza i posalac jej parametry: .new

możesz też użyć klauzuli Follows aby wywołać trigger po trigerze , Bez follows'a zmutujesz tabele - wyrzuci ci błąd

0

Dziękuję bardzo za pomoc, ale jednak zrezygnuję z takiego rozwiązania. Jest zbyt skomplikowane i nie jest wymagane na moim projekcie, pomyślę nad czymś innym.

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