Witaj Gościu! ( Zaloguj | Rejestruj )

Forum PHP.pl

> Blokowanie UPDATE w triggerze
Nexces
post
Post #1





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

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


Witam,
sprawa ma się następująco:
mam dwie tabele o identycznej strukturze:
  1. CREATE TABLE IF NOT EXISTS `trtest1` (
  2. `id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT,
  3. `value` varchar(30) character SET utf8 collate utf8_polish_ci NOT NULL,
  4. `ser` int(11) UNSIGNED NOT NULL,
  5. `time` int(11) NOT NULL,
  6. `info` text character SET utf8 collate utf8_polish_ci,
  7. PRIMARY KEY (`id`)
  8. ) ENGINE=InnoDB DEFAULT CHARSET=utf8 ;

różnią się tylko nazwą...
mam trigger'a który w momencie modyfikacji wiersza/wierszy z pierwszej tabeli poprzednie "wersje" przenosi do drugiej (śledzenie zmian swoiste)

pole `ser` które jest w tym przypadku numerem seryjnym nie może zostać w żasdnym przypadku zmodyfikwane...
pókico wyprodukowałem coś takiego:
  1. DELIMITER //
  2. CREATE TRIGGER `test`.`backup` BEFORE UPDATE ON `test`.`trtest1`
  3. FOR EACH ROW begin IF new.ser!=old.ser then
  4. SET new.info:=concat_ws('\n',
  5. old.info,
  6. '------------------------------------',
  7. NOW(),
  8. 'Próba modyfikacji numeru seryjnego!!',
  9. '------------------------------------\n'
  10. );
  11. SET new.ser:=old.ser;
  12. SET new.value:=old.value;
  13. SET new.time:=old.time;
  14. else
  15. INSERT INTO trtest2 (value,ser,time,info) SELECT value,ser,time,info FROM trtest1 WHERE id=NEW.id;
  16. SET new.time=UNIX_TIMESTAMP();
  17. end IF;
  18. end
  19. //
  20. DELIMITER ;


sprawuje się genialnie natomiast jest to app rozwijany ciągle i muszę mieć możliwość dość lekkiego dodawania kolejnych kolumn do tych tabel (w tej chwili jest raptem 20)...

zastanawiam się czy można tak opisać tego triggera, żeby:
po 1:
w przypadku próby zmiany numeru seryjnego zablokował akcję modyfikując tylko pole info
lub
przywrócił poprzednie wartości wszystkim kolumnom (w tej chwili jest tak to zrobione, jednak jest to o tyle niewygodne, że każde pole muszę osobno wpisać, a chcę tego uniknąć)

po 2:
wygodniejsze kopiowanie... znowuż w tej chwili muszę wszystkie pola wypisać, bo id jest auto_increment
insert into trtest2 select * from trtest2;
daje niezbyt przyjemny efekt w postaci dublowania klucza...

z góry dzięki za wszelkie propozycje (:
Go to the top of the page
+Quote Post
 
Start new topic
Odpowiedzi
Cezar708
post
Post #2





Grupa: Zarejestrowani
Postów: 1 116
Pomógł: 119
Dołączył: 10.05.2005
Skąd: Poznań

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


Cytat(Nexces @ 22.02.2008, 15:50:44 ) *
mysql chyba niezbyt potrafi coś takiego...

.. no fakt, też nic na ten temat nie znalazłem (może warto przejść na PostgreSQL?)
Cytat(Nexces @ 22.02.2008, 15:50:44 ) *
- wygląda na to, że rekord nie zostanie wypchnięty d drugiej tabeli

a dlaczego nie, to jest tylko ON UPDATE więc Twój insert działa dokładnie tak jak działał
Cytat(Nexces @ 22.02.2008, 15:50:44 ) *
- brak przechwycenia informacji o próbie modyfikacji

nie ma problemu, możesz i tę informację funkcjonalność do roli dopisać, żaden problem
Cytat(Nexces @ 22.02.2008, 15:50:44 ) *
- następuje insert i nowy rekord, a nie faktyczny update... (zapomniałem dodać, że `ser` czyli numer seryjny jest unique i musi być unique w pierwszej tabeli, nie może się zdażyć sytuacja, że będą dwa rekordy z tym samym numerem seryjnym w pierwszej tabeli)

faktycznie mój błąd, w roli po prostu zmień INSERT (...) na UPDATE (...) SET (...)
Cytat(Nexces @ 22.02.2008, 15:50:44 ) *
- dodatkowo mimo wszystko muszę wypisać kolejno kolumny... czego jak pisałem chciałbym uniknąć...

hmm tu można się zastanowić nad jedną sprawą, w MySQL jest coś takiego jak SHOW FIELDS (czy tam COLS lub FOR EACH ROW, nie pamiętam dokładnie) a potem poiterować po tego wyniku i odseparować tylko `ser`.. nie wiem czy da radę, nigdy nie próbowałem, może warto pomyśleć

Natomiast Twoje podejście ma jedną wadę, co by nie było UPDATE i tak się wykona.. więc jak ktoś by chciał zmienic ser to i tak by się zmienił.

Może również rozpatrzysz jedno podejście, tylko znowu nie jestem pewien, czy MySQL da sobie z tym radę
1. Użytkownikowi który łączy się z bazą poprzez skrypt PHP odbierasz prawa UPDATE do tej tabeli
2. Tworzysz widok, składający się tylko z kolumn, różnych od `ser`
3. Tworzysz ROLE lub TRIGGERA, na UPDATE (wiem, wiem, widoków nie można updatować, ale można na nie założyć triggery lub role, na pewno w PostgreSQL, w MySQL musisz sprawdzić tę możliwość)
4. Użytkownik łączący się przez skrypt może tylko wykonywać "UPDATE na WIDOKU", więc odcinasz go od możliwości zniszczenia kolumny `ser`

... nie wiem, czy pomogłem, ale niestety z MySQL zatrzymałem się w rozwoju, od dłuższego czasu go nie używam. Jeśli to nie jest problem to przenieś się na PostgreSQL i te wszystkie wymienione tutaj sprawy na pewno tam załatwisz,

Pozdrawiam
Go to the top of the page
+Quote Post

Posty w temacie


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: 9.10.2025 - 16:07