powered by simpleCommunicator - 2.0.60     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / PostgreSQL [игнор отключен] [закрыт для гостей] / Объясните как сделать правельный триггер
44 сообщений из 44, показаны все 2 страниц
Объясните как сделать правельный триггер
    #35417092
Shagrat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Есть таблицы в которых существует поле modify (timestamp without time zone) - это поле в которое записывается дата создания или изменения записи в таблицы.

Это поле обновляется через триггер по INSERT или UPDATE.

Тригер
Код: plaintext
1.
2.
3.
4.
CREATE TRIGGER ecus_modify
  BEFORE INSERT OR UPDATE
  ON ecus
  FOR EACH ROW
  EXECUTE PROCEDURE change_modify();

Функция
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
CREATE OR REPLACE FUNCTION change_modify()
  RETURNS "trigger" AS
$BODY$BEGIN
  IF NEW.modify = NULL THEN
    NEW.modify = now();
  END IF;  
  RETURN NEW;
END;$BODY$
  LANGUAGE 'plpgsql' VOLATILE;
ALTER FUNCTION change_modify() OWNER TO postgres;

Только вот проблема. Иногда нужно самому изменять значение этого поля. Пишу:
Код: plaintext
1.
UPDATE ecus SET modify='2008-07-08 10:26:53.575' WHERE id= 2643 ;

Только вот это поле всеравно заменяется значением из тригера.

Теперь вопрос. Где у меня ошибка. И поясните всетаки смысл AFTER и BEFORE.

Я себе предстовлял это так что когда ставшь признак BEFORE то заполенеие происходит так:
Сначало создается запись, потом срабатывает BEFORE и заполняет поля (вернее сам заполняешь в процедуре если надо), потом заполняются поля которые передал в INSERT потом срабатывает AFTER - который в свою очередь может заполнить даные (вернее сам заполняешь в процедуре если надо). А потом происходит запись данных.
...
Рейтинг: 0 / 0
Объясните как сделать правельный триггер
    #35417191
4321
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Код: plaintext
NEW.modify = NULL 
таки так низзя
Спросите у сервера
Код: plaintext
SELECT NULL =NULL
, посмотрите на результат

надо так.
Код: plaintext
NEW.modify IS NULL 
...
Рейтинг: 0 / 0
Объясните как сделать правельный триггер
    #35417194
MySQLCraft
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
IF NEW.modify IS NULL THEN
...
Рейтинг: 0 / 0
Объясните как сделать правельный триггер
    #35417242
Kruchinin Pahan
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Shagrat
Код: plaintext
1.
  IF NEW.modify = NULL THEN


Ошибка здесь. Сравнение NULL с другими значениями всегда возвращает NULL. А NULL это и не True и не False.
См. также IS NULL, Coalesce
Shagrat
Теперь вопрос. Где у меня ошибка. И поясните всетаки смысл AFTER и BEFORE.

Я себе предстовлял это так что когда ставшь признак BEFORE то заполенеие происходит так:
Сначало создается запись, потом срабатывает BEFORE и заполняет поля (вернее сам заполняешь в процедуре если надо), потом заполняются поля которые передал в INSERT потом срабатывает AFTER - который в свою очередь может заполнить даные (вернее сам заполняешь в процедуре если надо). А потом происходит запись данных.
Слегка иначе...
0. Делаем INSERT/UPDATE
1. Подготавливается новый ROW нужного типа, для которого последовательно отрабатывают DEFAULT'ы.
2. ROW передается в триггеры BEFORE (в порядке наименований триггеров). Только в триггере BEFORE можно поменять строку и откатить INSERT/UPDATE вернув NULL. В AFTER такого не проканает.
3. Запускается проверка Constraint и т.д. для новой версии строки.
4. Запускается триггер AFTER, он уже не влияет на строку через NEW, зато можно быть уверенным, что если до сюда дошло, то строка будет добавлена в базу (разве вилку из розетки выдернут). Здесь можно откатить всю транзакцию RAISE EXCEPTION.
5. Если до сюда дошло, то версия строки еще после нескольких преобразований попадает в базу. Но это еще более отдельная песня.
...
Рейтинг: 0 / 0
Объясните как сделать правельный триггер
    #35417316
Shagrat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Теперь становиться ясно (алгоритм примерно я так и представлял).

Только вот всеравно не работает. Когда меняешь другое поле триггер теперь не срабатывает. Странно.

Код: plaintext
1.
UPDATE ecus SET type= 1  WHERE id= 2643 ;
SELECT id, modify FROM ecus WHERE id= 2643 ;

Дата не обновляется, а если изменять поле то изменяется.

Вот полные исходники:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
CREATE TABLE ecus
(
  id serial NOT NULL,
  "type" integer NOT NULL,
  "name" character varying( 255 ) NOT NULL,
  "comment" character varying( 255 ),
  modify timestamp without time zone,
  CONSTRAINT ecus_pid PRIMARY KEY (id)
)
WITH (OIDS=FALSE);

CREATE TRIGGER ecus_modify
  BEFORE INSERT OR UPDATE
  ON ecus
  FOR EACH ROW
  EXECUTE PROCEDURE change_modify();

CREATE OR REPLACE FUNCTION change_modify()
  RETURNS "trigger" AS
$BODY$BEGIN
  IF NEW.modify IS NULL THEN
    NEW.modify = now();
  END IF;  
  RETURN NEW;
END;$BODY$
  LANGUAGE 'plpgsql' VOLATILE;
ALTER FUNCTION change_modify() OWNER TO postgres;

Подскажите ка всетаки это оживить.
...
Рейтинг: 0 / 0
Объясните как сделать правельный триггер
    #35417430
MySQLCraft
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Может быть 'modify' - зарезервированнное слово.
Возьми его везде в кавычки NEW.'modify'
...
Рейтинг: 0 / 0
Объясните как сделать правельный триггер
    #35417505
Фотография Ёш
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
MySQLCraftМожет быть 'modify' - зарезервированнное слово.
Возьми его везде в кавычки NEW.'modify'в SQL одинарные кавычки означают строковую константу. в pg используются двойные кавычки для экранирования идентификаторов.
...
Рейтинг: 0 / 0
Объясните как сделать правельный триггер
    #35417506
4321
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ShagratТеперь становиться ясно (алгоритм примерно я так и представлял).

Только вот всеравно не работает. Когда меняешь другое поле триггер теперь не срабатывает. Странно.

Код: plaintext
1.
UPDATE ecus SET type= 1  WHERE id= 2643 ;
SELECT id, modify FROM ecus WHERE id= 2643 ;

Дата не обновляется, а если изменять поле то изменяется.

Вот полные исходники:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
CREATE TABLE ecus
(
  id serial NOT NULL,
  "type" integer NOT NULL,
  "name" character varying( 255 ) NOT NULL,
  "comment" character varying( 255 ),
  modify timestamp without time zone,
  CONSTRAINT ecus_pid PRIMARY KEY (id)
)
WITH (OIDS=FALSE);

CREATE TRIGGER ecus_modify
  BEFORE INSERT OR UPDATE
  ON ecus
  FOR EACH ROW
  EXECUTE PROCEDURE change_modify();

CREATE OR REPLACE FUNCTION change_modify()
  RETURNS "trigger" AS
$BODY$BEGIN
  IF NEW.modify IS NULL THEN
    NEW.modify = now();
  END IF;  
  RETURN NEW;
END;$BODY$
  LANGUAGE 'plpgsql' VOLATILE;
ALTER FUNCTION change_modify() OWNER TO postgres;

Подскажите ка всетаки это оживить.
гыгы. еслиб в том месте, где работает триггер было бы действительно
Код: plaintext
NEW.modify IS NULL 
, то после срабатывания апдейта без триггера стало бы
Код: plaintext
NEW.modify IS NULL 
. как кстати тогда было бы присваивать в триггере
Код: plaintext
NEW.smfld =NULL 
если мы бы хотели очистить...

можно проверять
Код: plaintext
NEW.modify IS NULL OR  NEW.modify = OLD.modify
, ну или
Код: plaintext
 NEW.modify IS DISTINCT FROM OLD.modify
, или же руками послать SET modify = NULL. а получить обновку.
...
Рейтинг: 0 / 0
Объясните как сделать правельный триггер
    #35417536
Фотография Ёш
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ShagratТеперь становиться ясно (алгоритм примерно я так и представлял).

Только вот всеравно не работает. Когда меняешь другое поле триггер теперь не срабатывает. Странно.ничего странного, имхо у Вас проблема с логикой Вашего алгоритма. Попробуйте переформулировать задачу, абсолютно точно и подробно написать что именно Вы хотите что бы происходило :) например типа такого:
если вставляется новая запись с полем modify is null, то ....

если вставляется новая запись с полем modify > текущей даты, то ...

если вставляется новая запись с полем modify <= текущей даты, то ...

если обновляется запись в которой старое значение поля modify is null и новое значение поля modify is null, то ...
и так далее. тогда Вам имхо проще будет понять в чём у Вас проблема.
...
Рейтинг: 0 / 0
Объясните как сделать правельный триггер
    #35417641
Shagrat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Все просто.
Если вставляю или обновляю поле, без modify то дата ставится текущая сервера (тоесть триггером).

Если я сам прописываю в запросе поле modify то данные берутся из него.
...
Рейтинг: 0 / 0
Объясните как сделать правельный триггер
    #35417656
Kruchinin Pahan
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
4321
Код: plaintext
NEW.modify IS NULL OR  NEW.modify = OLD.modify
, ну или
Код: plaintext
 NEW.modify IS DISTINCT FROM OLD.modify
, или же руками послать SET modify = NULL. а получить обновку.
Не получится. У него триггер на INSERT/UPDATE. OLD для INSERT не определен. Надо разгребать 2 ситуации. TG_OP = 'INSERT' AND NEW.Modify IS NULL и TG_OP = 'UPDATE' AND Coalesce(NEW.Modify != OLD.Modify, True)

Как-то так.
...
Рейтинг: 0 / 0
Объясните как сделать правельный триггер
    #35417686
Shagrat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Все это можно но я не пойму почему просто

Код: plaintext
NEW.modify = now();

нельзя поставить, при этом все условия и так выполняется. Данные передаваемые запросом, должны заполниться всеравно после AFTER.
...
Рейтинг: 0 / 0
Объясните как сделать правельный триггер
    #35417801
Фотография Ёш
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ShagratВсе просто.
Если вставляю или обновляю поле, без modify то дата ставится текущая сервера (тоесть триггером).

Если я сам прописываю в запросе поле modify то данные берутся из него.
Вы ошибочно полагаете что не указанные в запросе обновления поля принимают значение null в тригере в псевдозаписе NEW, но это не так. не указанные в запросе поля заполняются _старыми_ значениями, поэтому Ваше условие "if new.modify is null then" сработает при обновлении только один раз - если у обновляемой записи в базе поле modify равно null.
...
Рейтинг: 0 / 0
Объясните как сделать правельный триггер
    #35418011
Shagrat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Я понимаю что значение принимается старое.

Мне непонятен другой факт. Последовательность присвоения значения.

Я полагаю что если вызов AFTER то это означает что событие возникнет перед заполнением полей из самого запроса.

Тоесть:
1. Поле заполняется старым значением
2. Вызов AFTER- в моем случаи заполнение в триггере (Достаточно без условий, простое присвоение)
3. Заполнение данными из самого запроса.
4. событие BEFORE (Как я понял там возможна только проверка данных).
5. Ну м сама запись данных в поле (Не учитываю транзакции, кеши, блокировки итд.)

Так вот вопрос почему, при запросе без поля modify данные, изменяет триггер. А при запросе с modify также данные заполняет триггер - но после не прописываются данные с самого запроса, а остаются триггерные. Получается триггер AFTER вызывается после заполнения данных самим запросом.

Тогда непонятно как сделать чтобы всетаки происходило по алгоритму описанному выше.
...
Рейтинг: 0 / 0
Объясните как сделать правельный триггер
    #35418153
Фотография Ёш
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ShagratМне непонятен другой факт. Последовательность присвоения значения.

Я полагаю что если вызов AFTER то это означает что событие возникнет перед заполнением полей из самого запроса.

Тоесть:
1. Поле заполняется старым значением
2. Вызов AFTER- в моем случаи заполнение в триггере (Достаточно без условий, простое присвоение)
3. Заполнение данными из самого запроса.
4. событие BEFORE (Как я понял там возможна только проверка данных).
5. Ну м сама запись данных в поле (Не учитываю транзакции, кеши, блокировки итд.)брр... у Вас видимо описка и вместо AFTER следует читать BEFORE, а вместо BEFORE - AFTER ? :)

у Вас конкретно всё перепутано :) должно быть имхо вот так:

1. Поле заполняется старым значением
3. Заполнение данными из самого запроса.
2. Вызов BEFORE - в моем случаи заполнение в триггере (Достаточно без условий, простое присвоение)
5. Ну м сама запись данных в поле (Не учитываю транзакции, кеши, блокировки итд.)
4. событие AFTER (Как я понял там возможна только проверка данных). -- можно update делать, только главное не зациклиться :)
...
Рейтинг: 0 / 0
Объясните как сделать правельный триггер
    #35418172
Фотография Ёш
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
BEFORE (ПЕРЕД) и AFTER (ПОСЛЕ) - это относительно внесения изменений в таблицу, а не относительно получения данных из запроса.

в тригере BEFORE таблица _ещё не изменена_, в тригере AFTER - таблица _уже изменена_


--
„Истина — это вовсе не то, что можно убедительно доказать, это то, что
делает всё проще и понятнее“ — Антуан де Сент-Экзюпери
...
Рейтинг: 0 / 0
Объясните как сделать правельный триггер
    #35418217
Shagrat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Ой извините, напутал, Я так и и мел ввиду.
По логике я все правильно понимаю.

Так вот у меня и не работает. Эта логика

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
CREATE TRIGGER ecus_modify
  BEFORE INSERT OR UPDATE
  ON ecus
  FOR EACH ROW
  EXECUTE PROCEDURE change_modify();

CREATE OR REPLACE FUNCTION change_modify()
  RETURNS "trigger" AS
$BODY$BEGIN
  NEW.modify = now();
  RETURN NEW;
END;$BODY$
  LANGUAGE 'plpgsql' VOLATILE;
ALTER FUNCTION change_modify() OWNER TO postgres;


Когда делаешь:
Код: plaintext
UPDATE ecus SET modify='2008-07-08 14:14:32.734' WHERE id= 2643 ;
Тогда дата устанавливается из триггера. А нужно (должна я так считаю по логике). Чтобы прописывалась из запроса.

Когда делаешь:
Код: plaintext
UPDATE ecus SET modify='2008-07-08 14:14:32.734' WHERE id= 2643 ;
Тогда все ок, тоесть тоже триггер прописывает дату - как и нужно.

По вашей схеме логике видно что сначало обрабатываются данные с запроса, а потом вызывается BEFORE - тогда понятно почему не работает.

Так всетаки получается ваша схема является правильной. - Если да то тогда действительно придется сравнивать старые данные данные.
...
Рейтинг: 0 / 0
Объясните как сделать правельный триггер
    #35418564
MySQLCraft
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
А не проще DEFAULT=now() определить и не париться с триггерами?
...
Рейтинг: 0 / 0
Объясните как сделать правельный триггер
    #35418566
MySQLCraft
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
DEFAULT now() без равно
...
Рейтинг: 0 / 0
Объясните как сделать правельный триггер
    #35418656
4321
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
MySQLCraftDEFAULT now() без равнодефолт не прокатит. на апдейт автору тоже надо модифачить.
...
Рейтинг: 0 / 0
Объясните как сделать правельный триггер
    #35418658
MySQLCraft
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
4321 MySQLCraftDEFAULT now() без равнодефолт не прокатит. на апдейт автору тоже надо модифачить.
SET modify = NULL

Пожертвовать удобством ради скорости и простоты
...
Рейтинг: 0 / 0
Объясните как сделать правельный триггер
    #35418659
Shagrat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Нет. Потомучто я могу его сменить. А мне нужно чтобы оно менялось после каждого INSERT или UPDATE
...
Рейтинг: 0 / 0
Объясните как сделать правельный триггер
    #35418699
Фотография Ёш
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
MySQLCraft 4321 MySQLCraftDEFAULT now() без равнодефолт не прокатит. на апдейт автору тоже надо модифачить.
SET modify = NULL

Пожертвовать удобством ради скорости и простотыSET modify = NULL запишет в modify null, а не default. что бы был default нужно так и писать: set modify = default
...
Рейтинг: 0 / 0
Объясните как сделать правельный триггер
    #35419037
MySQLCraft
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ёшчто бы был default нужно так и писать: set modify = default Точно! Забыл.
...
Рейтинг: 0 / 0
Объясните как сделать правельный триггер
    #35419044
MySQLCraft
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ShagratНет. Потомучто я могу его сменить. А мне нужно чтобы оно менялось после каждого INSERT или UPDATE Зачем "после", когда можно "во время"? Во время INSERT будет установлено ваше значение либо автоматически значение по дефолту. Во время UPDATE Вам придется каждый раз добавлять в выражение , modify = default или ваше значение. Если Вам это трудно или Вы не доверяете своей программе или пользователям нужно иметь доступ для прямого UPDATE и при этом таблица должна сама себя мониторить тогда извините. Так ли это необходимо?
...
Рейтинг: 0 / 0
Объясните как сделать правельный триггер
    #35419067
Фотография pamir
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
MySQLCraftТак ли это необходимо?Это логично. Всю логику, связанную с базой поместить в базу. Мало ли - сегодня у нас один клиент, а завтра ещё будет. И нужно везде не забыть про это поле? Нет уж, целостность и корректность данных нужно максимально отдавать на откуп базе. В идеале (если идеал этот достижим) клиент является лишь оболочкой, ничего не вычисляющей, но лишь принимающей данные от пользователя и возвращающие ему ответ. Но это идеал, конечно в реальности что-то клиент вычисляет. Но, повторюсь, такие вещи как целостность и непротиворечивость данных надо отдать БД.
...
Рейтинг: 0 / 0
Объясните как сделать правельный триггер
    #35419341
MySQLCraft
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
pamir MySQLCraftТак ли это необходимо?Это логично. Всю логику, связанную с базой поместить в базу. Мало ли - сегодня у нас один клиент, а завтра ещё будет. И нужно везде не забыть про это поле? Нет уж, целостность и корректность данных нужно максимально отдавать на откуп базе. В идеале (если идеал этот достижим) клиент является лишь оболочкой, ничего не вычисляющей, но лишь принимающей данные от пользователя и возвращающие ему ответ. Но это идеал, конечно в реальности что-то клиент вычисляет. Но, повторюсь, такие вещи как целостность и непротиворечивость данных надо отдать БД.
Для доступа к таблицам можно использовать представления, процедуры, функции, а для целостности внешние ключи и прочие ограничения. Зачем юзеру прямой доступ к таблицам, чтобы он имел возможность одним запросом положить сервер или грохнуть все данные?
...
Рейтинг: 0 / 0
Объясните как сделать правельный триггер
    #35419358
MySQLCraft
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
к томуже врядли время апдейта используется для поддержания целостности, скорее для мониторинга.
...
Рейтинг: 0 / 0
Объясните как сделать правельный триггер
    #35419561
4321
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
наверное в чистом виде такого поведения, чтобы при вставке/апдейте с SET моеполе = блаблабла вставлялось всегда и именно блаблабла а без - всегда в т.ч. апдейтилось на default добиться нельзя (можно с точностью до того, что когда и если
Код: plaintext
(олд!=нью)
, однако разрулив на 2 триггера (или ветки)-дабы "олд" не прорезался при инсерте) - что чревато тем, что при случайном совпадении нью=олд для большого апдейта с явным сетом эти записи таки отапдейтятся на дефолт вместо нью.

однако можно чтобы _всегда_ апдейтилось на дефолт, а для ручной правки с помощью скл-стейтмента сделать в триггере TG_ARGV[], для чего вести скажем служебную табличку с одной записью==полем==переменной. И такой апдейт делать в транзакции (или в спец хп)

Код: plaintext
1.
2.
3.
4.
BEGIN;
UPDATE "служебная" SET "режимапдейта" = - 1 ;
UPDATE mytable SET mylogfld = '2008-04-01' WHERE ....;
UPDATE "служебная" SET "режимапдейта" =  0 ;
COMMIT;

как юзать TG_ARGV[], читать здесь Триггер с параметрами
...
Рейтинг: 0 / 0
Объясните как сделать правельный триггер
    #35419630
Shagrat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
В моем проекте это поле нужно для возможности синхронизировать 2 базы.
1. Тоесть клиентская программа это поле не меняет, его меняет сама база.
2. Есть другая программа, которая по уникальному полю определяет новые записи, а по дате определяет измененные. И синхронизирует таблицы.

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

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

P.S Насчет делать обработку на стороне клиента (или синхронизатора). Это действительно не очень хорошый вариант.
1. Время на клиенте может стоять неверное (что встречалось нечасто). Можно конечно и применять функцию now() в запросе.
2. Так как таблиц таких многовато, то есть вероятность гдето в программе клиента забыть про это поле тем самым испортить актуальные данные при синхронизации баз (Что недопустимо).
3. Количество таблиц все время меняется. Создаются динамически по требованию.
...
Рейтинг: 0 / 0
Объясните как сделать правельный триггер
    #35419739
4321
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ну так сам бог велел ваш "синхронизатор" запущать в отдельной транзакции/сессии со сменой всего одной "переменной сессии" (под переменной сессии может подразумеваться любой временный объект, существующий либо только внутри транзакции, либо внутри сессии).
и тогда вам надо только поменять триггерную ф-ю на параметрическую, и процедуру старта "синхронизатора" (если тот держит одну сессию) - устанавливать там ту самую "переменную сессии".

Но если "синхронизатор" ваш коннектится внутри сеанса своей работы много и безсистемно (т.е. создает массу разных сеансов на сервере бд), - придется поменять все вызовы апдейта из синхронизатора (перед каждым апдейтом устанавливать "переменную сессии"), или все места установления начала сессии-соединения. Т.е. возможно - несколько мест. а не одно.
...
Рейтинг: 0 / 0
Объясните как сделать правельный триггер
    #35419807
Фотография pamir
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
MySQLCraftДля доступа к таблицам можно использовать представления, процедуры, функции, Да, можно

MySQLCraftа для целостности внешние ключи и прочие ограничения. Естественно

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

Я отвечал на:
MySQLCraftВо время UPDATE Вам придется каждый раз добавлять в выражение , modify = default или ваше значение. Если Вам это трудно или Вы не доверяете своей программе Зачем отдавать это клиентскому приложению, когда логичнее именно на триггерах или ещё как-то, но на стороне БД, поддерживать это поле.
К тому же, своей программе можно доверять, но завтра проект вырос и к таблице обращается ещё одна программа, написанная другими (другим отделом, другой группой в отделе - как угодно). А им забыли сообщить об этой особенности. Так нафига эти проблемы, когда поместив всю логику на сторону сервера, вы их избегаете. И при любой модификации логики (мало ли, нужно ставить не текущую дату, а дату на час меньше или больше) вам не нужно переписывать каждую программу или множество мест в программе - вы переписываете только серверную часть.
...
Рейтинг: 0 / 0
Объясните как сделать правельный триггер
    #35419867
Shagrat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Да дискуссия затянулась.

А можно реальный пример реализации. Если можно то рабочий.
...
Рейтинг: 0 / 0
Объясните как сделать правельный триггер
    #35419918
4321
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ShagratДа дискуссия затянулась.

А можно реальный пример реализации. Если можно то рабочий.чего ж реальней то

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
CREATE OR REPLACE FUNCTION check_myparam()
  RETURNS "int2" AS
$BODY$
   --на ваше усмотрение
   --в зависимости от метода хранения "переменной сеанса/транзакции"
$BODY$
  LANGUAGE 'sql' VOLATILE SECURITY DEFINER;
--
CREATE OR REPLACE FUNCTION change_modify()
  RETURNS "trigger" AS
$BODY$
DECLARE 
     param1 int2;
BEGIN
  param1=TG_ARGV[x];

  IF param1 =  0  THEN
    NEW.modify = now();
  END IF;  
  RETURN NEW;
END;
$BODY$
  LANGUAGE 'plpgsql' VOLATILE SECURITY DEFINER;
--
CREATE TRIGGER ecus_modify
  BEFORE INSERT OR UPDATE
  ON ecus
  FOR EACH ROW
  EXECUTE PROCEDURE change_modify(check_myparam());
--
...
Рейтинг: 0 / 0
Объясните как сделать правельный триггер
    #35419931
4321
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ShagratА можно реальный пример реализации. Если можно то рабочий.зы
лудше писадь таг:
автор"а можно примерный пример реальной реализации"
...
Рейтинг: 0 / 0
Объясните как сделать правельный триггер
    #35419982
Shagrat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Не стоит придираться к словам Ж).

Может есть способ увидеть данные переданные в запросе.
И в зависимости от них брать дату из запроса, или ставить свою
...
Рейтинг: 0 / 0
Объясните как сделать правельный триггер
    #35420066
4321
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ShagratМожет есть способ увидеть данные переданные в запросе.
И в зависимости от них брать дату из запроса, или ставить свою
добраться из триггерной фунции можно сюда
авторWhen a PL/pgSQL function is called as a trigger, several special variables are created automatically in the top-level block. They are:

NEW
Data type RECORD; variable holding the new database row for INSERT/UPDATE operations in row-level triggers. This variable is NULL in statement-level triggers.

OLD
Data type RECORD; variable holding the old database row for UPDATE/DELETE operations in row-level triggers. This variable is NULL in statement-level triggers.

TG_NAME
Data type name; variable that contains the name of the trigger actually fired.

TG_WHEN
Data type text; a string of either BEFORE or AFTER depending on the trigger's definition.

TG_LEVEL
Data type text; a string of either ROW or STATEMENT depending on the trigger's definition.

TG_OP
Data type text; a string of INSERT, UPDATE, or DELETE telling for which operation the trigger was fired.

TG_RELID
Data type oid; the object ID of the table that caused the trigger invocation.

TG_RELNAME
Data type name; the name of the table that caused the trigger invocation.

TG_NARGS
Data type integer; the number of arguments given to the trigger procedure in the CREATE TRIGGER statement.

TG_ARGV[]
Data type array of text; the arguments from the CREATE TRIGGER statement. The index counts from 0. Invalid indices (less than 0 or greater than or equal to tg_nargs) result in a null value. как видим - никаких TG_SETS[] и т.п аналогов там не наблюдается. ДУмаю - приведенный набор рулящих пимпочек триггера исчерпывающий.

Т.ч. либо вместо инсерт/апдейта пишите свои хп с полным перечнем и модифачьте поведение базы как требуется, либо придумывайте иной велосипед. (скажем -перехватывать текст стейтмента до его выполнения сервером и само-парсить в свой набор переменных сессии/транзакции. или, на худой, реализуйте вызов всех стейтментов из ваших прилад через экзекютирующую их ХП. но с предпарсингом (перед вызовом EXECUTE) строки передаваемого стейтмента в набор переменных.

Иде Я: Кстати, попробуйте написать DO INSTEAD RULE подменяющую вставку/апдейт в таблицу с дефолтами, на вставку/апдейт в таблицу _без_ дефолтов, а там проверьте, что придет вместо NEW - набор данных из апдейтируемой записи подменённой , или подменяющей таблицы. Вряд ли, предвкушаю, найдется дырка, но "а вдруг"?)
...
Рейтинг: 0 / 0
Объясните как сделать правельный триггер
    #35420100
4321
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
а так - ну попробуйте пользоваться ф-ей с одной дыркой в логике:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
CREATE OR REPLACE FUNCTION change_modify()
  RETURNS "trigger" AS
$BODY$BEGIN
IF TG_OP= 'UPDATE' THEN
  IF NEW.modify = OLD.modify THEN   
      --отработает с точностью до случайного совпадения в апдейтирующем сете
      NEW.modify = now();
  END IF;  
ELSE
  --вместо этой ветки просто пропишите DEFAULT на поле
  IF NEW.modify IS NULL Then

      NEW.modify = now();
  END IF;
END IF; 
  RETURN NEW;
END;$BODY$
  LANGUAGE 'plpgsql' VOLATILE;
...
Рейтинг: 0 / 0
Объясните как сделать правельный триггер
    #35420160
Shagrat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Я на этом и думал остановиться.

Но к сожалению ваш пример почемуто не работает. ПОЧЕМУТО :(
...
Рейтинг: 0 / 0
Объясните как сделать правельный триггер
    #35420478
Фотография Ёш
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ShagratЯ на этом и думал остановиться.

Но к сожалению ваш пример почемуто не работает. ПОЧЕМУТО :(рискну предположить, у Вас есть записи созданые до написания этого тригера и в них modify равен null. из-за этого при их модификации условие "IF NEW.modify = OLD.modify THEN" не выполниться и поле modify изменено не будет.

добавьте отладочный вывод - тогда будет понятно что происходит, например так:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
CREATE OR REPLACE FUNCTION change_modify()
  RETURNS "trigger" AS
$BODY$BEGIN
IF TG_OP= 'UPDATE' THEN
  raise notice 'change_modify: update';
  IF NEW.modify = OLD.modify THEN   
      raise notice 'change_modify: set new to now';
      --отработает с точностью до случайного совпадения в апдейтирующем сете
      NEW.modify = now();
  END IF;  
ELSE
  raise notice 'change_modify: NOT update';
  --вместо этой ветки просто пропишите DEFAULT на поле
  IF NEW.modify IS NULL Then
      raise notice 'change_modify: set new null to now';

      NEW.modify = now();
  END IF;
END IF; 
  RETURN NEW;
END;$BODY$
  LANGUAGE 'plpgsql' VOLATILE;
  
...
Рейтинг: 0 / 0
Объясните как сделать правельный триггер
    #35420624
Shagrat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Спасибо за подсказку про отладку. (postgres - изучаю недавно)

Все работает, если не выполнять один и тотже UPDATE

Всетаки придется делать через переменные в триггере.
...
Рейтинг: 0 / 0
Объясните как сделать правельный триггер
    #35420950
MySQLCraft
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
pamirЗачем отдавать это клиентскому приложению, когда логичнее именно на триггерах или ещё как-то, но на стороне БД, поддерживать это поле.
К тому же, своей программе можно доверять, но завтра проект вырос и к таблице обращается ещё одна программа, написанная другими (другим отделом, другой группой в отделе - как угодно). А им забыли сообщить об этой особенности. Так нафига эти проблемы, когда поместив всю логику на сторону сервера, вы их избегаете. И при любой модификации логики (мало ли, нужно ставить не текущую дату, а дату на час меньше или больше) вам не нужно переписывать каждую программу или множество мест в программе - вы переписываете только серверную часть.
Извиняюсь. Я неправильно выразился, Вы неправильно поняли. "Программе" в смысле хранимой процедуре или функции. Так и понимать везде во всех моих мостах в этой теме.
...
Рейтинг: 0 / 0
Объясните как сделать правельный триггер
    #35420966
4321
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Код: plaintext
IF NEW.modify = OLD.modify THEN 

надо поменять либо на
Код: plaintext
1.
2.
IF NOT  NEW.modify = OLD.modify THEN   
--do nothing
ELSE
либо на
Код: plaintext
IF NOT NEW.modify IS DISTINCT FROM OLD.modify THEN

но это, как уже предупреждалось, не спасет ситуацию при совпадении (т.е. ,в частности, при повторном запуске апдейта с прописанным SET mofify=xxxxx)
...
Рейтинг: 0 / 0
Объясните как сделать правельный триггер
    #35421005
MySQLCraft
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
... постах....

И всё таки, необходимость в такого рода тринггерах может появится только если пользователь имеет прямой доступ на UPDATE к таблице либо когда в процедуре или функции допускается изменение пользователем(не админом) даты обновления. Если юзер не имеет такого доступа, то триггер это лишнее звено. К чему я и веду.
...
Рейтинг: 0 / 0
44 сообщений из 44, показаны все 2 страниц
Форумы / PostgreSQL [игнор отключен] [закрыт для гостей] / Объясните как сделать правельный триггер
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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