Динамический триггер PL / PGSQL для всех таблиц в схеме - PullRequest
0 голосов
/ 14 декабря 2018

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

Я полагаю, что это не должно быть так сложно, как я делаю, потому что таблица в нашей схеме будет иметь точно такое же имя столбца «updated_at».

Одно решение, которое я попробовали думал, что сработает, превращая схему таблицы в массив и повторяя ее, вызывая / создавая триггер каждую итерацию.Но у меня нет тонны psql опыта, поэтому я нахожу себя в поисках нескольких часов, чтобы решить эту маленькую вещь.

SELECT ARRAY (
            SELECT
                table_name::text
            FROM 
                information_schema.tables

            WHERE table_schema = 'public') as tables;

Я также попробовал:

DO $$
DECLARE
    t text;
BEGIN
    FOR t IN 
        SELECT table_name FROM information_schema.columns
        WHERE column_name = 'updated_at'    
    LOOP 
        EXECUTE format('CREATE TRIGGER update_updatedAt
                        BEFORE UPDATE ON %I
                        FOR EACH ROW EXECUTE PROCEDURE updated_at()',
                        t);
    END loop;
    END;
    $$ language 'plpgsql';

Процедура:

CREATE OR REPLACE FUNCTION updated_at()
RETURNS TRIGGER AS $$
BEGIN
    NEW.updated_at = now();
    RETURN NEW;
END;
$$ language 'plpgsql';

1 Ответ

0 голосов
/ 14 декабря 2018

Ваш DO блок работает.Единственная проблема в том, что мы не можем иметь одно и то же имя триггера для нескольких триггеров.Таким образом, вы можете добавить суффикс / префикс table_name для имени триггера.

DO $$
DECLARE
    t text;
BEGIN
    FOR t IN 
        SELECT  table_name FROM information_schema.columns
             WHERE column_name = 'updated_at'    
    LOOP 


        EXECUTE format('CREATE TRIGGER update_updatedAt_%I
                        BEFORE UPDATE ON %I
                        FOR EACH ROW EXECUTE PROCEDURE updated_at()',
                        t,t);
    END loop;
    END;
$$ language 'plpgsql';

Кроме того, вы можете добавить проверку, чтобы убедиться, что триггер уже существует в information_schema.triggers, чтобы быть безопасным.

IF NOT EXISTS ( SELECT 1 from information_schema.triggers 
                     where trigger_name = 'update_updatedat_'|| t)                                                                                      
  THEN
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...