2011-02-01 2 views
1

У меня есть таблица "Candidates" с id (первичным ключом) и application_counter
и таблицами "Applications" с внешним ключом (candidate_id). Я хочу, чтобы application_counter был изменен каждый раз, когда приложение было добавлено или удалено (или изменено путем изменения candidate_id).Trigger в PostgreSQL

Все, что я могу сделать, это написать:

CREATE TRIGGER myTrigger AFTER INSERT OR DELETE OR UPDATE 
ON "Applications" FOR EACH ROW 
EXECUTE PROCEDURE funcname (arguments) 

И вопрос Как я могу написать триггер?

Сводка со страницы http://www.postgresql.org/docs/8.1/interactive/sql-createtrigger.html

CREATE TRIGGER name { BEFORE | AFTER } { event [ OR ... ] } 
ON table [ FOR [ EACH ] { ROW | STATEMENT } ] 
EXECUTE PROCEDURE funcname (arguments) 
+1

И ваш вопрос? –

+0

Хорошо, и в чем вопрос? Кстати, функция триггера не может принимать аргументы, проверьте руководство: http://www.postgresql.org/docs/current/interactive/plpgsql-trigger.html –

ответ

3

Я бы использовал таблицу, две таблицы и подсчитал строки в таблице applications. (См. COUNT().) Триггеры могут быть отключены; эта точка зрения всегда даст вам правильный ответ.

(Позже...)

Я понимаю, что вы хотите, чтобы ограничить строки-кандидата в таблице «приложения» к 3 или меньше. В этом случае я считаю, что лучше использовать ограничение CHECK() на «приложения», а не комбинацию триггера на «приложениях» и ограничение CHECK() на «кандидатов».

Для этого в PostgreSQL вам необходимо использовать функцию и вызвать функцию из CHECK(). (Насколько я знаю. Вы все еще не может выполнить произвольные SELECT заявления в CHECK() ограничений, верно?) Итак, вы создали бы эту функцию,

CREATE FUNCTION num_applications(cand_id integer) 
    RETURNS integer AS 
$BODY$ 

    DECLARE 
    n integer; 
    BEGIN 
    select count(*) 
    into n 
    from applications 
    where (candidate_id = cand_id); 

    return n; 
    END; 
$BODY$ 
LANGUAGE plpgsql; 

, а затем вы бы добавить ПРОВЕРКИ() ограничение к табличным «приложениям».

ALTER TABLE applications 
    ADD CONSTRAINT max_of_three CHECK (num_applications(candidate_id) < 3); 

"< 3", потому что CHECK() ограничение вычисляется до добавления строки. Вероятно, стоит проверить, как это ведет себя с отложенными ограничениями. Если у меня будет время позже, я сделаю это.

+0

+1 Кажется, что триггер переполнен (если он не предназначен для обучения) –

+0

Мне нужен тригер, потому что на 'application_counter' есть условие CHECK, в котором говорится, что каждый кандидат может отправить максимум 3 приложения. –

+0

Вы также можете использовать SELECT count() в триггере ... быстрая также, если есть полезный индекс для кандидата_ид. – Daniel

3
CREATE TRIGGER myname AFTER INSERT, DELETE OR UPDATE 
ON table applications 
EXECUTE PROCEDURE myfunc(); 

CREATE FUNCTION myfunc() RETURNS TRIGGER AS 
BEGIN 
    IF TG_OP != 'DELETE' THEN 
     update candicate set application_count = application_count + 1 where id = new.candidate_id; 
    END IF; 
    IF TG_OP != 'INSERT' THEN 
     update candicate set application_count = application_count + 1 where id = old.candidate_id; 
    END IF; 
END; 

Я надеюсь, что вы получите идею ... теперь работает также с обновленной candidate_id лет.

+0

Как я могу написать эту функцию, чтобы делать то, что хочу ? Я имею в виду, как я могу получить идентификатор «Кандидатов». Может быть один (INSERT или DELETE) или два (UPDATE). –

+1

Внутри «myFunc()», для стороны «Вставка», «Обновить счетчик кандидатов, счетчик = счетчик + 1, где id = new.candidate_id». Для триггера удаления см. «Old.candidate.id». Обновления ничего не делают, если не возможно изменить поле кандидат_ид, и в этом случае вы уменьшаетесь со старого и увеличиваете новый. –

+0

Это может быть новый вопрос, но ... Как предотвратить обновление в столбце «кандидат_ид»? –

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