2017-06-30 18 views
0

私はポストグルを使用しています。 のは、私は、次のトリガを作成するつもりですとしましょう:主キーの列名が不明な場合、トリガー機能で主キーの値を取得する方法は?

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; 

私はすべてのテーブルには名前「ID」との主キーを持っている多くのテーブルで、このトリガーを使用したくない(表にはで何の「ID」列を持つことはできませんすべて)。 だから私はどのように列名に関係なく、私のトリガー機能で主キーを使用する方法を見つける必要があります。 これをどうすれば実現できますか?

+0

.. – JeffUK

+1

http://8kb.co.uk/blog/2015/01([こちら]を参照してください。/19/copy-pavel-stehules-simple-history-table-but-the-jsonb-type /)または[ここ](http://okbob.blogspot.co.uk/2015/01/most-simply -implementation-of-history.html)、一般的な監査トリガーの2つのソリューション –

答えて

0

PostgreSQLのバージョンは何ですか? PostgreSQLのカタログを照会して、必要なものを達成する必要があります。以下のスクリプトを参照してください:

あなたのPostgreSQLにはJSONBのサポート(9.4+)があると仮定しています。私はあなたが鍵を識別するためにinformation_schema.columnsを使用して、各テーブルに対して動的に生成する必要があると思う

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