2013-10-08 3 views
0

Есть ли Postgres TRIGGER? S транзакционный по умолчанию вроде (я читал) в MySQL?Значение предельного поля со значением из другой таблицы перед записью

Я создал TRIGGER procedure, который использует простой IF ограничить значение столбца со значением другого TABLE с последующим UPDATE, если лимит нарушен.

Я бы предпочел, чтобы быть в одном TRANSACTION, но если я оберните IF ... THEN UPDATE с BEGIN ... COMMIT, он дает ошибку

SQL error: 

ERROR: syntax error at or near ";" 
LINE 2:   BEGIN; 
        ^

ли TRIGGER сек TRANSACTION аль по умолчанию ? Если нет, как можно сделать TRIGGERTRANSACTION al?

код

Это ON INSERT OR UPDATE из articles:

BEGIN 
    BEGIN; /* this first TRANSACTION line causes error */ 
    IF (NEW.votes_used > (SELECT votes_available FROM vote_totals 
    WHERE vote_totals.user_id = NEW.user_id)) THEN 
     UPDATE articles SET votes_used = (SELECT votes_available FROM vote_totals 
     WHERE vote_totals.userID = NEW.user_id) WHERE user_id = NEW.user_id; 
    END IF; 
    COMMIT; /*last TRANSACTION line */ 
    RETURN NULL; 
END; 

Я бы много, а делать CHECK или FOREIGN, чтобы пресечь это в зародыше, прежде чем данные даже получает, но я дон Не знаю, как это сделать с FOREIGN, и я читал, что CHECK s не может использовать подзапросы. Кажется, я читал, что это путь, но я должен сообщить, что я дБ noob.

+1

Триггер работает в любой транзакции событие стрельбы было. Таким образом, любое изменение триггера будет отменено или передано с внешним откатом или фиксацией. Но триггер - это плохой выбор, когда вы хотите ограничить значение столбца. Почему бы не использовать ограничение внешнего ключа или контрольное ограничение –

+0

@a_horse_with_no_name Я попытался выполнить 'CHECK', но подзапросы не разрешены. как я могу сделать это с помощью «FOREIGN», если значения из другой таблицы являются переменными и связаны другим столбцом? будет редактировать, чтобы показать ... ty! –

+0

Извините, что информации недостаточно, чтобы дать вам ответ. На самом деле сам вопрос кажется довольно сомнительным. –

ответ

1

Вам не нужно UPDATE внутри триггера. Вы можете присвоить значение NEW.votes_used

использовать что-то вроде:

BEGIN 
    IF (NEW.votes_used > (SELECT votes_available FROM vote_totals 
    WHERE vote_totals.user_id = NEW.user_id)) THEN 
     NEW.votes_used := (SELECT votes_available FROM vote_totals 
     WHERE vote_totals.userID = NEW.user_id); 
    END IF; 
    RETURN NEW; 
END; 

Или

BEGIN 
    NEW.votes_used := LEAST(NEW.votes_used, (SELECT votes_available 
              FROM vote_totals 
              WHERE vote_totals.userID = NEW.user_id)); 
    RETURN NEW; 
END; 

Это должно быть BEFORE UPDATE триггер работать. (И как все BEFORE UPDATE триггеры должны RETURN NEW).

Если вы хотите эмулировать проверочное ограничение с триггером - попробовать что-то вроде:

BEGIN 
    IF (NEW.votes_used > (SELECT votes_available 
          FROM vote_totals 
          WHERE vote_totals.user_id = NEW.user_id)) 
    THEN RAISE EXCEPTION 'Not enough votes'; 
    END IF; 
    RETURN NEW; 
END; 
+0

очень круто! новый трюк для инструмента, tyvm! это «FOREIGN», возможно, как лошадь, или это лучший способ пойти? (plz извините мой noobity), что второй является удивительным! –

+0

@ Gracchus Я не думаю, что внешний ключ возможен - он может только проверять на равенство. Но вы можете эмулировать ограничение 'CHECK' с помощью триггера. Если триггер 'RAISE EXCEPTION' прерывает транзакцию, как регулярное ограничение' CHECK'. –

+0

perfecto! tyvm! –

0

Триггеры являются транзакционными в том смысле, что их действия можно отбросить назад. Вам не нужно ничего делать, чтобы заставить их работать так.

Ошибка синтаксиса. Трудно сказать вам больше, не видя кода.

+0

ty! поэтому postgre 'TRIGGER' блокирует все, что он читает и пишет до конца? будет редактировать с большим количеством кода. –

+0

Не совсем; только записи (или явные вызовы блокировки) вызывают блокировку. Для получения дополнительной информации о том, как PostgreSQL реализует транзакции, прочитайте о MVCC по адресу http://www.postgresql.org/docs/9.1/static/mvcc.html – matthudson

+0

@ Gracchus: (это Postgres, а не Postgre) - триггер не будет " блокировать "все. Все утверждения, выполняемые в триггере, запускаются в * той же * транзакции, что и оператор, запускающий триггер. Если инструкция стрельбы откатывается назад, то любое изменение, выполняемое триггером. Если заявка на стрельбу зафиксирована, это также может быть сделано с помощью триггера. –

Смежные вопросы