MySQL Fire Trigger zarówno dla wstawiania, jak i aktualizacji

111

Czy możliwe jest uruchomienie wyzwalacza mysql zarówno dla zdarzeń wstawiania, jak i aktualizacji tabeli?

Wiem, że mogę wykonać następujące czynności

CREATE TRIGGER my_trigger
    AFTER INSERT ON `table`
    FOR EACH ROW
BEGIN
.....
END //

CREATE TRIGGER my_trigger
    AFTER UPDATE ON `table`
    FOR EACH ROW
BEGIN
.....
END //

Ale jak mam to zrobić

CREATE TRIGGER my_trigger
    AFTER INSERT ON `table` AND
    AFTER UPDATE ON `table`
    FOR EACH ROW
BEGIN
.....

Czy to możliwe, czy muszę użyć 2 wyzwalaczy? Kod jest taki sam dla obu i nie chcę go powtarzać.

Adam S-Price
źródło

Odpowiedzi:

126

Musisz utworzyć dwa wyzwalacze, ale możesz przenieść wspólny kod do procedury i sprawić, by oba wywoływały procedurę.

derobert
źródło
3
Czy możesz podać zabawkowy przykład dla tych z nas, którzy nie są zaznajomieni ze składnią?
Zxaos
3
@Zxaos: Proponuję zacząć od dev.mysql.com/doc/refman/5.1/en/create-procedure.html (który zawiera kilka przykładów) i zadawać własne pytania w razie potrzeby.
derobert
2
Szkoda, że ​​nie możemy używać operatorów AND / OR tak jak w Oracle, tym bardziej, że nie możemy przekazać przez parametr do procedury całych zmiennych OLD i NEW. Mój kod będzie> 2x
Mikel
Ten jest przydatny dla programisty, który nigdy nie
idzie
1
@luismartingil prawdopodobnie wiąże się z dodatkowymi kosztami wywoływania procedury, a nie wstawiania jej. Ale w zamian otrzymujesz łatwiejszą konserwację i gwarancję, że kod dwóch wyzwalaczy nie rozejdzie się przypadkowo.
derobert
46

W odpowiedzi na żądanie @Zxaos, ponieważ nie możemy mieć operatorów AND / OR dla wyzwalaczy MySQL, zaczynając od kodu, poniżej znajduje się kompletny przykład, aby osiągnąć to samo.

1. Zdefiniuj wyzwalacz INSERT:

DELIMITER //
DROP TRIGGER IF EXISTS my_insert_trigger//
CREATE DEFINER=root@localhost TRIGGER my_insert_trigger
    AFTER INSERT ON `table`
    FOR EACH ROW

BEGIN
    -- Call the common procedure ran if there is an INSERT or UPDATE on `table`
    -- NEW.id is an example parameter passed to the procedure but is not required
    -- if you do not need to pass anything to your procedure.
    CALL procedure_to_run_processes_due_to_changes_on_table(NEW.id);
END//
DELIMITER ;

2. Zdefiniuj wyzwalacz UPDATE

DELIMITER //
DROP TRIGGER IF EXISTS my_update_trigger//

CREATE DEFINER=root@localhost TRIGGER my_update_trigger
    AFTER UPDATE ON `table`
    FOR EACH ROW
BEGIN
    -- Call the common procedure ran if there is an INSERT or UPDATE on `table`
    CALL procedure_to_run_processes_due_to_changes_on_table(NEW.id);
END//
DELIMITER ;

3. Zdefiniuj wspólną PROCEDURĘ używaną przez oba te wyzwalacze:

DELIMITER //
DROP PROCEDURE IF EXISTS procedure_to_run_processes_due_to_changes_on_table//

CREATE DEFINER=root@localhost PROCEDURE procedure_to_run_processes_due_to_changes_on_table(IN table_row_id VARCHAR(255))
READS SQL DATA
BEGIN

    -- Write your MySQL code to perform when a `table` row is inserted or updated here

END//
DELIMITER ;

Zauważasz, że dbam o przywrócenie separatora, kiedy skończę z definiowaniem wyzwalaczy i procedur w mojej firmie.

Al Zziwa
źródło
1
Co jest IN table_row_id VARCHAR(255)w tym przypadku? Mam na myśli, jak definiujesz, który wiersz zostanie wstawiony lub zaktualizowany?
VaTo
13

niestety nie możemy używać w MySQL po opisie INSERT lub UPDATE , jak w Oracle

Jeff_Alieffson
źródło