2009-09-11 2 views
3

Ради примера, рассмотрим таблицуPostgres обновить поле даты, когда логическое поле установлено значение истинного

create table foo (
    contents text NOT NULL, 
    is_active boolean NOT NULL DEFAULT false, 
    dt_active date 
) 

вставить запись:

insert into foo (contents) values ('bar') 

До сих пор, так хорошо , Позже, теперь я хочу, чтобы «активировать» запись:

update foo set is_active = true 

То, что я хотел бы сделать, когда is_active изменяется от false до true, для dt_active установлен в now(). Для бонусных очков было бы неплохо, если is_active изменен с true на fals e, dt_active установлен в null, но я могу жить без этого.

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

Я в тупике о том, как вытащить текущую запись в базе данных в триггере (я использую plpgsql), чтобы сравнить «затем» с «сейчас». Указатели на примеры кода или фрагменты значительно оценены.

+0

Если у вас уже есть код, было бы легче указать ошибки или завершить его, чем дать вам полное решение с нуля. Поэтому, если можете, опубликуйте его. –

ответ

4
CREATE OR REPLACE FUNCTION trg_update_foo() RETURNS TRIGGER AS 
$BODY$ 
BEGIN 
    IF OLD.is_active = false AND NEW.is_active = true THEN 
     NEW.dt_active := now(); 
    ELSIF OLD.is_active = true AND NEW.is_active = false THEN 
     NEW.dt_active := NULL; 
    END IF; 
    RETURN NEW; 
END; 
$BODY$ 
LANGUAGE 'plpgsql'; 
CREATE TRIGGER trg_update_foo BEFORE UPDATE ON foo FOR EACH ROW EXECUTE PROCEDURE trg_update_foo(); 

Должно работать. Для получения дополнительной информации проверьте pl/PgSQL Triggers manual, а за дополнительные баллы - целые plPgSQL документов.

+0

с 'CREATE TRIGGER trg_update_foo_t ПЕРЕД ОБНОВЛЕНИЕМ НА foo ДЛЯ КАЖДОЙ ПРОГРАММЫ EXECUTE ROW trg_update_foo();' и мы в бизнесе. – dland

2

Вы пробовали manual?

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

Вы можете просто проверить значение столбца OLD по OLD.is_active. Точно так же вы можете изменить значения, которые следует поместить в базу данных, как NEW.dt_active := now();

Надеюсь, что это hels.

4

В вашей процедуре триггера plpgsql у вас есть доступ к некоторым специальным переменным типа записи, которые называются NEW и OLD, которые созданы для вас.

В UPDATE или INSERT триггер, NEW будет представлять запись новой строки базы данных.

В UPDATE или DELETE триггер, OLD будет представлять значение исходной строки базы данных.

В других контекстах утверждения эти переменные записи будут NULL.

Поэтому кажется, что вам нужно создать триггер INSERT OR UPDATE, который смотрит на значения OLD.is_active и NEW.is_active.

Вот страница документация - http://www.postgresql.org/docs/8.1/interactive/plpgsql-trigger.html Эта страница содержит пример кода для plpgsql, который использует NEW и OLD

2
CREATE FUNCTION actrigger() RETURNS TRIGGER AS $$ BEGIN 
    IF TG_OP='UPDATE' THEN 
     IF NEW.is_active THEN 
      IF NOT OLD.is_active THEN 
       NEW.dt_active := current_date; 
      END IF; 
     ELSIF NEW.dt_active IS NOT NULL 
      NEW.dt_active := NULL; 
     END IF; 
    END IF; 
    RETURN NEW; 
END; $$ LANGUAGE plpgsql; 
CREATE TRIGGER foobefore BEFORE UPDATE ON foo FORR EACH ROW 
    EXECUTE PROCEDURE actrigger(); 

И вы можете позаботиться о INSERT который тоже будет очень похоже, за исключением не должны относиться к OLD.

+1

В чем смысл проверки TG_OP, когда ваш триггер явно установлен как «ПЕРЕД ОБНОВЛЕНИЕМ»? – 2009-09-11 11:21:00

+0

И ELSE - он установит dt_Active на нуль при каждом обновлении строки, когда is_active = false, а не только когда он изменен с true на false. – 2009-09-11 11:22:22

+0

depesz, я думал о расширении его до 'insert', но потом решил оставить его как упражнение для читателя ;-) Что касается установки dt_active, я подумал об этом. Он должен быть уже NULL, если он неактивен. Означает ли это, что он будет делать фактическую запись из-за этого задания? Конечно, если вы сделаете 'UPDATE .. SET dt_active = NULL', но это задание выглядело таким безвредным для меня ;-) Можете ли вы подтвердить, что это будет дополнительная запись? –

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