powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / PostgreSQL [игнор отключен] [закрыт для гостей] / Помогите написать триггер
8 сообщений из 8, страница 1 из 1
Помогите написать триггер
    #39015797
PCContra
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Есть таблица
Код: sql
1.
logs.pidlist (pid INT NOT NULL UNIQUE, pnum INT NOT NULL UNIQUE);


В таблицу поступает только команда INSERT.
Не могу написать триггер, который бы проверял перед вставкой, есть ли такие значения уже в таблице. Если есть, то удалял бы их, а новые вставлял.
Например, если уже есть такой pid, или pnum, или и то и другое, то удалить такие строчки, новую вставить в любом случае. И после этих действий выполнял бы вакуум таблицы.
Я сам мало этими командами занимался, опыта совсем нет по ним.

Спасибо за внимание
...
Рейтинг: 0 / 0
Помогите написать триггер
    #39015798
Фотография vyegorov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
PCContra,

У вас обе колонки UNIQUE, все уже и так будет как вы хотите, без триггеров.
...
Рейтинг: 0 / 0
Помогите написать триггер
    #39015814
qwwq
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
PCContra,

в http://www.postgresql.org/docs/9.1/static/plpgsql-trigger.html#PLPGSQL-TRIGGER-SUMMARY-EXAMPLE
блок <<insert_update>> делает то, что вам нужно

где то битым словом была нужная вам ф-я. наверное в старой доке.
не тригерный вариант --тут

http://www.postgresql.org/docs/current/static/plpgsql-control-structures.html#PLPGSQL-UPSERT-EXAMPLE
переделайте
...
Рейтинг: 0 / 0
Помогите написать триггер
    #39015979
PCContra
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Сделал так, посмотрите пожалуйста:
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
CREATE  TABLE  logs.pidlist (
pid INT NOT NULL UNIQUE,
pnum INT NOT NULL UNIQUE REFERENCES pd.persons (pnum) ON UPDATE CASCADE ON DELETE RESTRICT
);

CREATE OR REPLACE FUNCTION logs.logs_pidlist ()  RETURNS  TRIGGER  AS
$$
BEGIN
    LOOP
        BEGIN
            INSERT INTO logs.pidlist (pid, pnum) VALUES (NEW.pid, NEW.pnum);
            RETURN;
        EXCEPTION WHEN unique_violation THEN
            -- Do nothing, and loop to try the INSERT again.
        END;
    END LOOP;
END;
$$
LANGUAGE plpgsql;

CREATE  TRIGGER  log INSTEAD OF  INSERT  
ON  logs.pidlist
FOR  EACH  ROW  EXECUTE  PROCEDURE  
logs.logs_pidlist ();



Ошибка SQL:

ОШИБКА: отсутствует выражение (примерное положение: ";")
LINE 12: RETURN;


Почему ругается не return?


И еще: я правда не понимаю, зачем там второй begin end (я его оставил из мануала).
И третье: может это можно как переписать по-короче и по-производительне е?
...
Рейтинг: 0 / 0
Помогите написать триггер
    #39015997
qwwq
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
RTFMTriggers that are specified to fire INSTEAD OF the trigger event must be marked FOR EACH ROW, and can only be defined on views .


PCContraЕсть таблица
Код: sql
1.
logs.pidlist (pid INT NOT NULL UNIQUE, pnum INT NOT NULL UNIQUE);


В таблицу поступает только команда INSERT.
Не могу написать триггер, который бы проверял перед вставкой, есть ли такие значения уже в таблице. Если есть, то удалял бы их, а новые вставлял.
Например, если уже есть такой pid, или pnum, или и то и другое, то удалить такие строчки, новую вставить в любом случае. И после этих действий выполнял бы вакуум таблицы.
Я сам мало этими командами занимался, опыта совсем нет по ним.

Спасибо за внимание
извините, сразу не вчитался.

у вас 2 потенциальных ключа. а не ключевой набор с ресурсами.

т.е. если pid уже есть, но с другим pnum, надо заапдейтить pnum при это pid-е. а если есть pnum с другим pid -- надо заапдейтить тот pnum (поменять ему pid). и, наконец если есть 2 записи -- одна с таким pnum а ДРУАЯ с таким pid -- надо выбросить ОБЕ старые ,и заложить новую . так, кажется следует из вашей постановки ? ничего не путаете ?

тогда всё немного сложнее .

Проще всего с помощью каскада безусловного DELETE | RETURN NEW; в BEFORE триггере. но вот с конкуренцией на инсертах (за оба ключа) надо побороться -- устроить на них очередь в момент входа в триггер -- т.е. еще даже перед DELETE. (чтобы delete опоздуна срабатывал только после коммита опередившей транзакции).

Это наверное удобнее сделать через pg_advisory_xact_lock(key1 int, key2 int)
вам надо залочить одним предложением 2 инта на разных ключах. т.е .взять в selecte 2 pg_advisory_xact_lock(2) с параметрами например oid pg_attribute-а -- первый параметр; и собственно значение этого поля -- второй. Поля у вас удачно -- интовые. были бы бигинты --пришлось бы что- то иное придумывать.
...
Рейтинг: 0 / 0
Помогите написать триггер
    #39016024
PCContra
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
qwwqт.е. если pid уже есть, но с другим pnum, надо заапдейтить pnum при это pid-е. а если есть pnum с другим pid -- надо заапдейтить тот pnum (поменять ему pid). и, наконец если есть 2 записи -- одна с таким pnum а ДРУАЯ с таким pid -- надо выбросить ОБЕ старые ,и заложить новую . так, кажется следует из вашей постановки ? ничего не путаете ?
Да, все именно так.
pid у меня - это результат от pg_backend_pid(), два одинаковых pid'а в один момент времени быть не может.
pnum - пользователь, два параллельных запроса от одного пользователя, наверное, тоже быть не могут. :-)
Старые строчки можно удалить, если хотя бы одно из значений совпадает.
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
CREATE OR REPLACE FUNCTION logs.logs_pidlist ()  RETURNS  TRIGGER  AS
$$
BEGIN
DELETE FROM logs.pidlist  WHERE pid=NEW.pid OR pnum=NEW.pnum;
VACUUM logs.pidlist;
--также выбрал вакуум для таблицы, он без лока - вроде бы то, что нужно
RETURN NEW;
END;
$$
LANGUAGE plpgsql;

CREATE  TRIGGER  log BEFORE  INSERT  
ON  logs.pidlist
FOR  EACH  ROW  EXECUTE  PROCEDURE  
logs.logs_pidlist ();



RTFMTriggers that are specified to fire INSTEAD OF the trigger event must be marked FOR EACH ROW, and can only be defined on views.
Я это прочитал как: Триггер, указанный как "вместо" должен быть для каждой строки для представлений (а для не представлений может быть указан как FOR STATEMENT). Ошибся.
...
Рейтинг: 0 / 0
Помогите написать триггер
    #39016041
PCContra
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
qwwq ,
спасибо!
...
Рейтинг: 0 / 0
Помогите написать триггер
    #39016508
qwwq
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
PCContra,

не за что.

у вас там конкуренция (по крайней мере за pid) невозможна физически -- т.ч. будет и так работать.
...
Рейтинг: 0 / 0
8 сообщений из 8, страница 1 из 1
Форумы / PostgreSQL [игнор отключен] [закрыт для гостей] / Помогите написать триггер
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]