Can a trigger create a TABLE when inserting data? I have a trigger that keeps track of history of table dev by inserting a row in table dev_hist:

CREATE OR REPLACE FUNCTION process_dev_hist() RETURNS TRIGGER AS $dev_hist$
    DECLARE action_name text;
    BEGIN
        IF TG_OP = 'DELETE' THEN
            OLD.timestamp := current_timestamp;
            action_name := 'deleted';
            INSERT INTO dev_hist SELECT action_name, user, OLD.*;
        ELSE
            NEW.timestamp := current_timestamp;
            IF (TG_OP = 'INSERT') THEN
                action_name := 'added';
            ELSIF (TG_OP = 'UPDATE') THEN
                action_name := 'modified';
            END IF;
            INSERT INTO dev_hist SELECT action_name, user, NEW.*;
        END IF;
        RETURN NULL; -- result is ignored since this is an AFTER trigger
    END;
$dev_hist$ LANGUAGE plpgsql;

DROP TRIGGER IF EXISTS dev_hist ON dev;
CREATE TRIGGER dev_hist AFTER INSERT OR UPDATE OR DELETE ON dev
    FOR EACH ROW EXECUTE PROCEDURE process_dev_hist();


Problem is, if table dev_hist doesn't exist, it throws error.

Is it possible to change it, so it would create table if it doesn't exist?
You can use INFORMATION_SCHEMA.TABLES to check if dev_hist table exists, if not you can create it in your trigger:

CREATE TABLE T (id int, name text);

CREATE OR REPLACE FUNCTION process_dev_hist() RETURNS TRIGGER AS $dev_hist$
    DECLARE action_name text;
    BEGIN

        -- add your catalog information.
        CREATE TABLE IF NOT EXISTS dev_hist
        (
            action text
        );

        IF TG_OP = 'DELETE' THEN
            action_name := 'deleted';
            INSERT INTO dev_hist SELECT action_name;
        ELSE
            IF (TG_OP = 'INSERT') THEN
                action_name := 'added';
            ELSIF (TG_OP = 'UPDATE') THEN
                action_name := 'modified';
            END IF;
            INSERT INTO dev_hist SELECT action_name;
        END IF;
        RETURN NULL; -- result is ignored since this is an AFTER trigger
    END;
$dev_hist$ LANGUAGE plpgsql;

DROP TRIGGER IF EXISTS dev_hist ON T;
CREATE TRIGGER dev_hist AFTER INSERT OR UPDATE OR DELETE ON T
    FOR EACH ROW EXECUTE PROCEDURE process_dev_hist();





INSERT INTO T VALUES (1);
DELETE FROM T WHERE id = 1;



1 rows affected

1 rows affected






SELECT * FROM dev_hist;



| action  |
| :------ |
| added   |
| deleted |



db&lt;>fiddle here