SQLinfo.ru - Все о MySQL Webew.ru: теория и практика веб-технологий

Форум пользователей MySQL

Задавайте вопросы, мы ответим

Вы не зашли.

#1 11.08.2009 17:13:35

vaspet
Завсегдатай
Зарегистрирован: 11.03.2009
Сообщений: 83

Как "пропустить" исполнение Тригеров в процедуре?

Сталкнулся с проблеммой НЕ вызова Тригерра из процедуры.

Мне нужно, что-бы вставки происходящие внутри процедуры не вызывали тригер на вставку.
Вообщем нужен механизм "отключить" временно тригер. Как такое можно реализовать?

Неактивен

 

#2 11.08.2009 17:17:52

LazY
_cмельчак
MySQL Authorized Developer and DBA
Зарегистрирован: 02.04.2007
Сообщений: 849

Re: Как "пропустить" исполнение Тригеров в процедуре?

Средствами MySQL нельзя никак - триггер безусловно выполняется при каждой вставке в таблицу, если только при вставке не произошла ошибка (поэтому есть грязный хак, который заключается в том, чтобы намеренно вызывать ошибку при вставке, однако, это плохая практика).

Корректное решение состоит в том, чтобы вместо триггера вставлять через процедуру. Или же в процедуре в нужном случае как-то специально исправлять действие триггера.

Неактивен

 

#3 11.08.2009 18:23:29

vaspet
Завсегдатай
Зарегистрирован: 11.03.2009
Сообщений: 83

Re: Как "пропустить" исполнение Тригеров в процедуре?

LazY написал:

...Корректное решение состоит в том, чтобы вместо триггера вставлять через процедуру....

Да нет Тригер тут какраз всегда должен выполнятся по-логике приложения. И делает он ето замечательно.
Просто есть Процедура, которая востанавливает BACKUP таблицы, словом:
TRUNCATE TABLE
+
INSERT INTO
и вот она не должна вызывать действий тригера

С truncate как раз все ок, он под Тригер не попадает, а вот как быть с INSERT?

LazY написал:

Или же в процедуре в нужном случае как-то специально исправлять действие триггера.

Вот-Вот
Хорелось бы что-то типа

SET @no_trigger = 1;

а в тригере
IF @no_trigger = 1 THEN ...

но есть ли такое или граблями как-то надо (записать значение в какую-нибудь таблицу...)?
Типа "системной" или "глобальной" переменной присвоить значение.

Отредактированно vaspet (11.08.2009 18:24:58)

Неактивен

 

#4 11.08.2009 18:52:49

paulus
Администратор
MySQL Authorized Developer and DBA
Зарегистрирован: 22.01.2007
Сообщений: 6757

Re: Как "пропустить" исполнение Тригеров в процедуре?

А чем Вам не нравится ровно тот способ, который Вы написали (через @no_trigger)?

Неактивен

 

#5 11.08.2009 23:22:32

vaspet
Завсегдатай
Зарегистрирован: 11.03.2009
Сообщений: 83

Re: Как "пропустить" исполнение Тригеров в процедуре?

Было бы удобно использовать для этого переменную, не нашел правда подходящей документации по поводу переменных в mysql.
Только синтаксис: SET [GLOBAL | SESSION] sql_variable=expression;

Но если я использую: SET a1='test';
получаю ошибку типа "системной переменной нет"
т.е. ето толко для каких-то внутренних (mysql) переменных.

методом "научного тыка" понял, что можно использовать: SET @a1='test';
тогда работает. Но что ето за переменная? локальная?
будет ли видна она в тригере так:

CREATE PROCEDURE...
BEGIN
  SET @no_trigger=1;
  INSERT... // вызывает работу тригера
  SET @no_triгger=0;
END
 

если она будет видна внутри тригера - хорошо. Но что-то мне подсказывает, что ето не так.

А что произойдет, если Процедура по каким-либо причинам прервет свое выполнение до строчки SET @no_trigger=0;
тригер не будет больше выполнятся!?

Отредактированно vaspet (11.08.2009 23:41:17)

Неактивен

 

#6 12.08.2009 00:27:46

vasya
Архат
MySQL Authorized Developer
Откуда: Орел
Зарегистрирован: 07.03.2007
Сообщений: 5842

Re: Как "пропустить" исполнение Тригеров в процедуре?

@var_name это пользовательская переменная, действует в течении сессии.
Т.е. когда для вас @no_trigger=1 для других пользователей эта переменная не определена, т.е. null

Подробнее о пользовательских переменных см.
http://sqlinfo.ru/forum/viewtopic.php?id=363

Неактивен

 

#7 12.08.2009 11:51:58

vaspet
Завсегдатай
Зарегистрирован: 11.03.2009
Сообщений: 83

Re: Как "пропустить" исполнение Тригеров в процедуре?

Если @no_trigger=1 ето пользовательская переменная и действует в течении сессии и для других пользователей эта переменная не определена, то
тригер который будет вызван в процедуре её не увидит (он выполняется в своей сессии (от другово пользователя)?), так?


CREATE PROCEDURE...
BEGIN
  SET @no_trigger=1;
  INSERT... // вызывает работу тригера
  SET @no_triгger=0;
END
 


кстати mysql не принимает следующее: (что сильно затрудняет изучение - не показывает где ошибка а выдаёт в консоль список каких-то типов/слов)
разобрался - знаки табуляции ему не нравились


DROP TRIGGER IF EXISTS `apo_customers`.`medi_ins`;
DELIMITER //
CREATE TRIGGER `apo_customers`.`medi_ins` AFTER INSERT ON `apo_customers`.`medication`
 FOR EACH ROW
     BEGIN
         IF @no_trigger = 0 THEN
         
            SET @task = "ERSTELLT";
           
            IF NEW.parent_id > 0
            THEN
                SET @task = "NACHFOLGE_ERSTELLT";
            END IF;
           
            INSERT INTO
                apo_customers.medication_history
            SET
                id = NEW.id,
                parent_id = NEW.parent_id,
                user_id = NEW.user_id,
                patient_id = NEW.patient_id,
                physician_id = NEW.physician_id,
                pharmaceutical_id = NEW.pharmaceutical_id,
                daily_dose = NEW.daily_dose,
                active = NEW.active,
                task = @task;
        END IF;
    END;
//
DELIMITER ;
 


П.С: Хотелось бы наужится пользоватся тригерами и процедурами, но наталкнулся на отсутствие подробного описания тех или иных функций (синтаксис и пример) для (IF а что если if вложенный? [IF a=b IF c=d SELECT 1; ENDIF; END IF;]?, FOR EACH, когда BEGIN END, ...)
P.P.S. если кто-нибудь кинет в меня ссылкой - буду только рад.

Отредактированно vaspet (12.08.2009 11:56:28)

Неактивен

 

#8 12.08.2009 14:50:56

vaspet
Завсегдатай
Зарегистрирован: 11.03.2009
Сообщений: 83

Re: Как "пропустить" исполнение Тригеров в процедуре?

етот метод работает.
Спасибо всем за помощь.

Неактивен

 

Board footer

Работает на PunBB
© Copyright 2002–2008 Rickard Andersson