简体   繁体   中英

PL/PGSQL dynamic trigger for all tables in schema

I am looking to automate each table update with an automatic update of the updated_at column. I am able to make this work for a specific table using a trigger. But my main goal, which I can't find anywhere, is to create a function that dynamically grabs all the tables in the schema, and creates that same trigger and only changing the table name that the trigger is referencing to. For the life of me I can't figure it out.

I believe this shouldn't be as tricky as I'm making it as ever table in our schema will have the exact same column name of 'updated_at'.

One solution that I tried and thought would work was turning the table schema into an array, and iterating through that to invoke/create the trigger each iteration. But I don't have a ton of psql experience so I am finding myself googling for hours to solve this one little thing.

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

            WHERE table_schema = 'public') as tables;

I have also tried:

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';

Procedure:

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

Your DO block works. The only problem with it is we can't have same Trigger name for multiple triggers. So, you can either add a table_name suffix/prefix for the Trigger 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';

Additionally you may add a check to see if the trigger already exists in information_schema.triggers to be safe.

IF NOT EXISTS ( SELECT 1 from information_schema.triggers 
                     where trigger_name = 'update_updatedat_'|| t)                                                                                      
  THEN

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM