Postgres обновляет поле даты, когда для логического поля установлено значение true - PullRequest
3 голосов
/ 11 сентября 2009

Для примера рассмотрим таблицу

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), чтобы сравнить «тогда» с «сейчас». Мы очень ценим указатели на примеры кода или фрагменты кода.

Ответы [ 4 ]

4 голосов
/ 11 сентября 2009
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 Руководство по триггерам , а для дополнительных точек - целые plPgSQL документы.

4 голосов
/ 11 сентября 2009

Внутри вашей триггерной процедуры 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 голосов
/ 11 сентября 2009
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.

2 голосов
/ 11 сентября 2009

Вы пробовали руководство ?

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

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

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

...