如果主键列名称未知,如何在触发器函数中获取主键值?

Don*_*ote 5 sql postgresql

我正在使用 postgres。假设我要创建以下触发器:

CREATE OR REPLACE FUNCTION auditlogfunc() RETURNS TRIGGER AS $example_table$
   BEGIN
      INSERT INTO AUDIT(EMP_ID, ENTRY_DATE) VALUES (new.ID, current_timestamp);
      RETURN NEW;
   END;
$example_table$ LANGUAGE plpgsql;
Run Code Online (Sandbox Code Playgroud)

我想对许多表使用这个触发器,并不是每个表都有名为“id”的主键(表可以根本没有“id”列)。所以我需要以某种方式找出如何在我的触发器函数中使用主键,无论它有哪个列名。我怎样才能做到这一点?

Mic*_*zzi 6

What's your PostgreSQL version? You must query PostgreSQL catalog to achieve what you want. See script below:

I'm assuming that your PostgreSQL has JSONB support (9.4+).

CREATE TABLE public.test_table 
(
    id BIGINT NOT NULL,
    a_column TEXT NOT NULL,
    CONSTRAINT test_tablepkey PRIMARY KEY (id)
);

CREATE OR REPLACE FUNCTION auditlogfunc() RETURNS TRIGGER AS $example_table$
DECLARE
    reg_id JSONB; 
    affected_row JSON;   
BEGIN

    IF TG_OP IN('INSERT', 'UPDATE') THEN
        affected_row := row_to_json(NEW);
    ELSE
        affected_row := row_to_json(OLD);
    END IF;

    --Get PK columns
    --You may want to extract this to a SQL function
    WITH pk_columns (attname) AS (
        SELECT 
            CAST(a.attname AS TEXT) 
        FROM 
            pg_index i 
            JOIN pg_attribute a ON a.attrelid = i.indrelid AND a.attnum = ANY(i.indkey) 
        WHERE 
            i.indrelid = TG_RELID 
            AND i.indisprimary
    )
    SELECT 
        json_object_agg(key, value) INTO reg_id
    FROM 
        json_each_text(affected_row)
    WHERE 
        key IN(SELECT attname FROM pk_columns);

    --Raise collected PK
    RAISE INFO 'PK: %', reg_id;

    --TODO: your insert into audit table goes here
    RETURN NEW;
END;
$example_table$ LANGUAGE plpgsql;

CREATE TRIGGER tg_audit_cadprodu_row AFTER INSERT OR UPDATE OR DELETE
  ON public.test_table FOR EACH ROW EXECUTE PROCEDURE public.auditlogfunc();

--A simple test
INSERT INTO test_table VALUES (CAST((random() * 10000) AS INTEGER), 'Test');
Run Code Online (Sandbox Code Playgroud)