powered by simpleCommunicator - 2.0.60     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / PostgreSQL [игнор отключен] [закрыт для гостей] / Объясните как сделать правельный триггер
19 сообщений из 44, страница 2 из 2
Объясните как сделать правельный триггер
    #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
19 сообщений из 44, страница 2 из 2
Форумы / PostgreSQL [игнор отключен] [закрыт для гостей] / Объясните как сделать правельный триггер
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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