Witaj Gościu! ( Zaloguj | Rejestruj )

Forum PHP.pl

> Jak modyfikować tabele z ustawionym na niej triggerem
woj_tas
post
Post #1





Grupa: Zarejestrowani
Postów: 230
Pomógł: 36
Dołączył: 31.03.2006
Skąd: Zielona Góra

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


Witam.

Mam tabele odpowiedzi (id, tytul, kolejnosc) oraz ustawionego na niej wyzwalacz:
  1. CREATE OR REPLACE
  2. TRIGGER ODPOWIEDZI_TRG
  3. AFTER DELETE ON ODPOWIEDZI
  4. FOR EACH ROW
  5. DECLARE
  6. nr_pytania NUMBER(4);
  7. nr_kolejnosc NUMBER(4);
  8. BEGIN SELECT pytanie_id, kolejnosc INTO nr_pytania, nr_kolejnosc FROM odpowiedzi WHERE odpowiedz_id = :OLD.odpowiedz_id;
  9. UPDATE odpowiedzi SET kolejnosc = kolejnosc-1 WHERE (kolejnosc > nr_kolejnosc AND pytanie_id = nr_pytania);
  10. END;

Jak widac chciałbym w wyzwalaczu zmodyfikować kolumnę kolejność. Niestety otrzymuję błąd:
Cytat
tabela ODPOWIEDZI ulega mutacji, wyzwalacz/funkcja może tego nie widzieć


Pytanie brzmi w jaki sposób mogę działać na tabeli na której utworzony jest wyzwalacz?

Dodam tylko że znalazłem odpowiedź aby usunąć FOR EACH ROW ale niestety wtedy nie będę miał dostępu do :NEW i :OLD

Ten post edytował woj_tas 3.04.2008, 22:39:38
Go to the top of the page
+Quote Post
 
Start new topic
Odpowiedzi (1 - 6)
lukskrodz
post
Post #2





Grupa: Zarejestrowani
Postów: 2
Pomógł: 0
Dołączył: 19.05.2008

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


A probowałes usunać
FOR EACH ROW
i zamiast tego dać:
REFERENCING NEW AS NEW OLD AS OLD;
Go to the top of the page
+Quote Post
redman2
post
Post #3





Grupa: Zarejestrowani
Postów: 104
Pomógł: 3
Dołączył: 13.10.2004

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


Wydaje mi sie, ze nie mozna dzialac na tabeli na ktorej masz ustawiony trigger. Poza tym to zapytanie nie ma sensu, jako ze nie wywolujesz komedny DELETE. Jaki bylby sens ustawiac trigger na siebie samego ?

Wejdz do EM i w dziale TRIGGER pozamieniaj tabele i zobacz czy sie skompiluje.

Powodzenia
Go to the top of the page
+Quote Post
ciapol
post
Post #4





Grupa: Zarejestrowani
Postów: 2
Pomógł: 0
Dołączył: 31.01.2009

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


Cytat(lukskrodz @ 19.05.2008, 22:54:07 ) *
A probowałes usunać
FOR EACH ROW
i zamiast tego dać:
REFERENCING NEW AS NEW OLD AS OLD;

Po co pisać, że masło jest maślane?
Jeśli chcesz zmienić nazwę referencji to wpisujesz REFERENCING NEW AS inna_nazwa_new OLD AS inna_nazwa_OLD. A ponieważ nie zmieniłeś nic w nazewnictwie wpisujesz po prostu REFERENCING.
To raz. Dwa, Panie woj_tas nie można ustawić wyzwalacza bezpośrednio na DELETE relacji, a na perspektywie jak najbardziej :-) Kolejna sprawa jest taka, że można operować na relacji na której jest ustawiony trigger, ale należy to robić w sposób logiczny np:
  1. CREATE OR REPLACE TRIGGER weryfikacja_numeru_nowej_bandy
  2. BEFORE INSERT ON Bandy
  3. FOR EACH ROW
  4. DECLARE
  5. ile_jest bandy.nr_bandy%TYPE;
  6. BEGIN SELECT COUNT(*) INTO ile_jest FROM Bandy;
  7. IF :NEW.nr_bandy!=(ile_jest+1) THEN :NEW.nr_bandy:=(ile_jest+1); END IF;
  8. END;
  9. /
  10. SHOW ERRORS;

Powodzenia i pozdrawiam
MW
Go to the top of the page
+Quote Post
WojtusJ
post
Post #5





Grupa: Zarejestrowani
Postów: 6
Pomógł: 1
Dołączył: 27.02.2009

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


Panie ciapol, oczywiście muszę się z Panem zgodzić jednak pojawiło się trochę filozofii z Pańskiej wypowiedzi...

Po pierwsze - sprawa kosmetyczna - posługuje się Pan błędną terminologią. Pojęcie "relacji" występuje jedynie w Teorii Relacyjnej, podobnie jak krotka, atrybut, dziedzina czy schemat relacji. W naszym przypadku mowa ewidentnie o modelu fizycznym relacyjnej bazy danych, zatem powinno używać się pojęcia "Tabela" po prostu :-)

Po drugie działanie triggerem na tabeli na której jest ustawiony w sposób logiczny to bardziej jakaś magia. Problem woj_tas'a pojawił się z tego względu, że wyzwalacze FOR EACH ROW oraz wszystkie wywołane pośrenio przez DELETE CASCADE nie mogą czytać ani pisać w mutating tables, czyli tabelach które wyzwoliły zmianę (z małym wyjątkiem o którym zaraz) - to jest ten problem. W starszych wersjach nie mogły również modyfikować kluczy w constraining tables.

Uściślając (wspomniany wyjątek), wyzwalacz FOR EACH ROW nie ma dostępu do innych wierszy zmieniającej się tabeli, CHYBA ŻE jest to wyzwalacz BEFORE | AFTER INSERT FOR EACH ROW wyzwolony przez wstawianie pojedynczego wiersza.

Ta 'logika' wyczerpuje temat ;-)

Powodzenia!
Go to the top of the page
+Quote Post
kshysieq
post
Post #6





Grupa: Zarejestrowani
Postów: 1
Pomógł: 0
Dołączył: 22.11.2009

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


A próbowaliście używać PRAGMA AUTONOMOUS_TRANSACTION; W niektórych szczególnych przypadkach może być bardzo pomocne.
Przykład zaczerpnięty ze strony http://www.psoug.org/reference/table_trigger.html

  1. CREATE OR REPLACE TRIGGER t_trigger
  2. AFTER INSERT ON t1 FOR EACH ROW
  3.  
  4. DECLARE
  5. PRAGMA AUTONOMOUS_TRANSACTION;
  6. i PLS_INTEGER;
  7. BEGIN
  8. SELECT COUNT(*)
  9. INTO i
  10. FROM t1;
  11.  
  12. INSERT INTO t2
  13. VALUES
  14. (i);
  15. COMMIT;
  16. END;/


Go to the top of the page
+Quote Post
wiiir
post
Post #7





Grupa: Zarejestrowani
Postów: 260
Pomógł: 34
Dołączył: 22.02.2010

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


no przeciez jest after delete, wiec usuwasz i dajesz :old na rekord ktorego nie ma, dlatego triger tego nie widziec (IMG:style_emoticons/default/biggrin.gif) .. daj before

btw.. nawet nie wiedzialem ze to tak stary temat ;D

Ten post edytował wiiir 27.08.2010, 22:19:35
Go to the top of the page
+Quote Post

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

 



RSS Aktualny czas: 5.04.2026 - 16:15