wielowierszowy insert + dwa triggery _ null

0

Mama taki problem:

Tabela glowna - IMIE , NUMER - imie i numer to klucz główny

Probuje napisać trigger który przy wielowierszowym INSERTcie, jeżeli napotka na NULL w polu NUMER ma wyłapywać taki wiersz, zmieniać w locie null na wartość -1 i każdy nastepny wiersz z NULLem zamienić na o jeden mniejszy niż poprzedni np -1, -2 , -3 itd

np.
insert all into table glowna values ('pierwszy', null)
into table glowna values ('drugi', null)
select * from dual;

i przykladowy trigger

create or replace trigger przyklad
before insert on glowna
for each row
declare
licznik integer := -1;
begin

if :new.numer is null
then
:new.gromadka:= licznik;
licznik := licznik -1;
end if;

end ;

cos tu pokręciłem bo wstawia we wszystkie wiersze -1

może jakaś podpowiedź ?

baza oracle 12c

Pozdrawiam

0

Trigger dla kazdego wiersza wykonuje sie na nowo, wiec zgodnie z warunkiem najpierw :new.gromadka jest ustawiany na -1 a potem licznik ustawiany na -2. I dokladnie to samo odbywa sie dla kazdego wiersza.
Musisz zrobic:
Sprawdzenie czy w tabeli do ktorej insertujesz znajduja sie juz liczby mniejsze od zera.
Jesli nie - wstawiasz -1
Jesli tak pobierasz najmniejsza liczbe do zmiennej, odejmujesz od niej jeden i dopiero przypisujesz do :new.gromadka.

0

ze sprawdzaniem tabeli czy są mniejsze od zera sobie poradziłem, dalszy krok trigera to załatwia, chodzi o to że nawet jak zrobiłem tak jak wspomniałeś nadal przy odpaleniu trigera wartość początkowa licznika jest -1 i za każdym wierszem zaczyna od -1
albo czegoś nie rozumiem.

0

Przetlumacz sobei na język polski:
for each row
declare
licznik integer := -1

0

Marcin, no doszedłem że to w tym tkwi problem i dlatego szukam rozwiązania jak to załatwić. Ze względu na klucz nie mogę do tabeli wrzucać null stąd ten pomysł z liczbami ujemnymi no i żeby nie było błędu insertu zduplikowanego klucza pomysł z postkrementacją.
Zacząłem kombinować z sekwencją i działa ale jest problem żeby zaczynała zawsze od -1 (przy kolejnym wielowierszowym insercie). Walczę dalej.

0

to jeszcze raz to napiszę
MUSISZ POBRAĆ NAJMNIEJSZĄ WARTOŚĆ Z TABELI I ZMNIEJSZYĆ JĄ O JEDEN. Żaden licznik tutaj nie da rady.

0

Nie wiem jak zdefiniowane jest pole NUMER (znakowe czy liczba; pewnie znakowe), ale możesz je wykorzystać.

if :new.numer is null
then
  :new.numer:= (select coalesce(min(numer),0)-1 
                            from glowna 
                            where numer starting with '-');
end if; 

Jeżeli NUMER ma typ liczbowy, to

starting with '-'

możesz po prostu zamienić na <0

Innym rozwiązaniem jest użycie SEQUENCE (generatora).

0

Nie mogę skanować tabeli głownej na której wykonywany jest INSERT bo ORACLE 12c przy wielowierszowym insercie nie pozwala na to. Pozostaje więc pozostaje sekwencja. Dzięki.

0

Chciałbym reaktywować temat bo mam kolejną zagwozdkę.
Napisałem trigger AFTER INSERT który ma wybierać z tabeli Temporary kolejne wiersze wstawione tam w wyniku działania wielowierszowego inserta i triggera BEFORE. Kompiluje się tylko w momencie działania zawsze wybiera pierwszy wiersz :( Doszedłem już dlaczego , bo przy warunku where rownum =1 zawsze podstawia mu się pierwszy wiersz ... logiczne. No i brakuje mi pomysłu jak zrobić żeby przy kolejnym przebiegu sięgał po kolejny wiersz z temporary.

0

zrobiłem w drugim triggerze delete ale teraz przy insercie wywala mi że no data found
coś chyba popieprzyłem albo czego nie rozumiem, zrobiłem sobie tablicę debagującą do której wpisuję wartości wybrane w select z drugiego trigera i zawsze bierze pierwszy wiersz z temporary i dla niego się wykonuje.... może jak wkleję cały trigger wyjdzie gdzie zrobiłem błąd :
nowy to jest tablica temporary

create or replace trigger nowy_skarb
after insert on grota_skarbow
declare
suma integer;
nazwa nowy.nazwa%type;

begin
select nowy.nazwa into nazwa from nowy where rownum=1;

select sum(ilosc) into suma from grota_skarbow where nazwa_skarby= nazwa;
insert into debag2 values (nazwa, suma);
if suma <0
then raise_application_error (-20001,'manko');
end if;

--delete from nowy where nazwa=nazwa ;

end nowy_skarb;
/
show errors

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