如何获取函数中一行的主键值?

问题描述

我在 postgres 中有一个函数,可以在我的表中发送有关 CRUD 操作的事件。然而问题是它只适用于具有 id 列作为主键的表。如何更改它以便我可以使用任何列作为主键?

CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
SET search_path = PUBLIC,pg_catalog;
CREATE OR REPLACE FUNCTION psycopg2_pgevents_create_event() RETURNS TRIGGER AS $function$
  BEGIN
    IF (TG_OP = 'DELETE') THEN
        PERFORM pg_notify('psycopg2_pgevents_channel',json_build_object(
            'event_id',uuid_generate_v4(),'event_type',TG_OP,'schema_name',TG_TABLE_SCHEMA,'table_name',TG_TABLE_NAME,'row_id',OLD.id            -------- this is not always "id"
        )::text
     );
         RETURN NULL;
    ELSE
        raise notice 'Value: %',NEW;
        PERFORM pg_notify('psycopg2_pgevents_channel',json_build_object(
                'event_id',NEW.id,-------- this is not always "id"
                'data',NEW
        )::text
    );
    RETURN NULL;
    END IF;
  END;
$function$ LANGUAGE PLPGsql;
SET search_path = "$user",PUBLIC;

解决方法

如果你只有一个主键列,而你只想要它的值,你可以使用:

to_jsonb(NEW)->>(
  SELECT attname
  FROM pg_attribute
  JOIN pg_index ON indexrelid = attrelid
  WHERE indrelid = TG_RELID
    AND indisprimary
)

如果您有多个主键列,和/或您想以 {"key":"value"} 格式检索 PK,您可以使用:

SELECT jsonb_object_agg(attname,to_jsonb(NEW)->attname)
FROM pg_attribute
JOIN pg_index ON indexrelid = attrelid
WHERE indrelid = TG_RELID
  AND indisprimary