Создание одной функции на все триггеры

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

Но не нашел возможности сказать функции, какое поле яв-ся идентификатором. Лишь нашел возможность указать таблицу...

Спасибо за любую помощь.

Структура спец. таблицы ALL_MAX_ID следующая: два поля NAMETABLE - хранящая перечень наименований всех обслуживаемых таблиц и поле MAX_ID - со значеним самого большого идентификатора, который был.

CREATE FUNCTION SAVE_MAX_ID() RETURNS TRIGGER AS $$
BEGIN
	  	UPDATE ALL_MAX_ID SET MAX_ID=NEW.id
		WHERE NAMETABLE=TG_TABLE_NAME AND MAX_ID < NEW.id;
RETURN NEW;
END;
$$ LANGUAGE plpgsql; 
 
CREATE TRIGGER SAVE_MAX_ID AFTER INSERT ON mytable
    FOR EACH ROW EXECUTE PROCEDURE SAVE_MAX_ID();

Опции просмотра комментариев

Выберите предпочитаемый вами способ показа комментариев и нажмите "Сохранить настройки" для активации изменений.

> Но не нашел возможности

> Но не нашел возможности сказать функции, какое поле яв-ся идентификатором.
Вы не про это случайно?
http://postgresql.ru.net/docs/extented_FAQ.html#Q003
Для полей таблицы это также справедливо

Я не знаю, о каких функция

Я не знаю, о каких функция идет речь в примере.
Я говорю о тех, которые пишутся на процедурном языке и вызываются как триггеры.
То есть об этом
http://postgresql.ru.net/manual/plpgsql-trigger.html
Они имеют набор встроенных переменных.
Из них в TG_TABLE_NAME хранится имя таблицы, на которой сработал триггер, вызвавший функцию.
А в переменной NEW хранится запись, вот как из этой записи выцепить значение столбца, не указывая напрямую его наименование в функции.

Есть вообще возможности в запросе обращаться к полям таблицы, не используя их наименования, а например позицию в таблице?

Ещё раз внимательно

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

Вот такая конструкция делает

Вот такая конструкция делает то, что мне нужно и пока меня устраивает.
Помогла вот эта статья
http://wiki.postgresql.org/wiki/PL/pgSQL_Dynamic_Triggers
А вот в том документе про хранимые процедуры указывался процесс компиляции, но у меня его нет или я снова, чего-то не так прочитал?
Спасибо за терпение)

CREATE OR REPLACE FUNCTION SAVE_MAX_ID()
RETURNS TRIGGER
LANGUAGE plpgsql 
AS $$
BEGIN
EXECUTE 'UPDATE TABLE_ID SET MAX_ID = ($1).' || TG_ARGV[0] || ' WHERE NAMETABLE= ' || quote_literal(TG_TABLE_NAME) || ' AND MAX_ID < ($1).' || TG_ARGV[0] USING NEW;
RETURN NEW;
END;
$$; 
 
CREATE TRIGGER MAX_ID_1 AFTER INSERT ON table1
    FOR EACH ROW EXECUTE PROCEDURE SAVE_MAX_ID('id');
 
CREATE TRIGGER MAX_ID_2 AFTER INSERT ON table2
    FOR EACH ROW EXECUTE PROCEDURE SAVE_MAX_ID('id');

Ещё раз попытаюсь

Ещё раз попытаюсь объяснить.
Когда вы создаёте функцию она компилируется и сохраняется для дальнейшего использования. Это не зависит от вашего желания. Это просто происходит.
На момент компиляции функция ДОЛЖНА знать с какой КОНКРЕТНО таблицей она будет работать и с какими КОНКРЕТНО полями. В противном случае на этапе компиляции невозможно проверить корректность работы функции, ибо в процессе работы функция ДОЛЖНА быть уверена, что именно эти поля ТОЧНО найдутся в той таблице и что они будут того самого типа. Теперь понятно?

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

Осталось прояснить тогда вот

Осталось прояснить тогда вот такой момент.

CREATE FUNCTION SAVE_MAX_ID() RETURNS TRIGGER AS $$
BEGIN
	  	UPDATE TABLE_ID SET MAX_ID=NEW.id
		WHERE NAMETABLE=TG_TABLE_NAME AND MAX_ID < NEW.id;
RETURN NEW;
END;
$$ LANGUAGE plpgsql; 

TG_TABLE_NAME - это переменная, а значит имеется невыполнение условия "функция ДОЛЖНА знать с какой КОНКРЕТНО таблицей она будет работать". А вот такая функция все-таки работала.

Раз EXECUTE - зло во благо, то это костыль. Может можно обойтись без EXECUTE? (Если наименование ключевого поля не id, как бы его вот простенько обозначить)

Но я не требую, пуская и так поработает пока.

> А вот такая функция

> А вот такая функция все-таки работала.
Судя по запросу TG_TABLE_NAME это не имя таблиц и даже не имя поля, а ЗНАЧЕНИЕ для конкретного поля в конкретной таблице, т.е. условия наличия конкретной таблицы и конкретного поля в функции соблюдены. А значения могут меняться, потому что иначе функции не нужны были бы :)

Опции просмотра комментариев

Выберите предпочитаемый вами способ показа комментариев и нажмите "Сохранить настройки" для активации изменений.

Back to top

(С) Виктор Вислобоков, 2008-2023