X-Original-To: pgsql-sql-postgresql.org@postgresql.org Received: from localhost (mx1.hub.org [200.46.208.251]) by postgresql.org (Postfix) with ESMTP id 1D3B59FB347 for ; Mon, 31 Jul 2006 02:31:07 -0300 (ADT) Received: from postgresql.org ([200.46.204.71]) by localhost (mx1.hub.org [200.46.208.251]) (amavisd-new, port 10024) with ESMTP id 47020-09 for ; Mon, 31 Jul 2006 02:31:02 -0300 (ADT) X-Greylist: from auto-whitelisted by SQLgrey- Received: from web56612.mail.re3.yahoo.com (web56612.mail.re3.yahoo.com [66.196.97.56]) by postgresql.org (Postfix) with SMTP id 2137D9FB346 for ; Mon, 31 Jul 2006 02:31:01 -0300 (ADT) Received: (qmail 28268 invoked by uid 60001); 31 Jul 2006 05:30:57 -0000 DomainKey-Signature: a=rsa-sha1; q=dns; c=nofws; s=s1024; d=yahoo.com; h=Message-ID:Received:Date:From:Subject:To:Cc:In-Reply-To:MIME-Version:Content-Type:Content-Transfer-Encoding; b=5obrNaBkr887rwEGzb6NG+VN+JHAYrdl6lNVoM0QtXljjWgKDdyEp3HYkosm5Y6DoMBsJ8uloBee7WYyKMNh0v28VYV4C4yR+KQ4bKfw979fql4fqSLdnga4Fk2HqVu5BHb5ZP+v3iYPMn/79ztzMNvHnaVWk5eDgp5jCVI4xVQ= ; Message-ID: <20060731053057.28266.qmail@web56612.mail.re3.yahoo.com> Received: from [203.143.27.130] by web56612.mail.re3.yahoo.com via HTTP; Sun, 30 Jul 2006 22:30:57 PDT Date: Sun, 30 Jul 2006 22:30:57 -0700 (PDT) From: Thusitha Kodikara Subject: Re: Triggers using PL/pgSQL To: Aaron Bono Cc: pgsql-sql@postgresql.org In-Reply-To: MIME-Version: 1.0 Content-Type: multipart/alternative; boundary="0-715009522-1154323857=:24141" Content-Transfer-Encoding: 8bit X-Virus-Scanned: Maia Mailguard 1.0.1 X-Spam-Status: No, hits=4.141 tagged_above=0 required=5 tests=AWL, DNS_FROM_RFC_ABUSE, DNS_FROM_RFC_POST, DNS_FROM_RFC_WHOIS, HTML_40_50, HTML_MESSAGE, UPPERCASE_25_50 X-Spam-Level: **** X-Archive-Number: 200607/370 X-Sequence-Number: 25944 --0-715009522-1154323857=:24141 Content-Type: text/plain; charset=iso-8859-1 Content-Transfer-Encoding: 8bit Hello, Thanks a lot Aaron for the very quick and simple example. I just checked it on 7.4.5 also and it worked. I'll be able to continue with my development using the syntax of that example. Regards, -Thusitha Aaron Bono wrote: On 7/30/06, Thusitha Kodikara wrote: Hello, I am interested in developing some triggers to keep track of records that are changed (possibly the changes of one or more specific columns). In addition to keeping the new values, I also need to keep the old values (may be on a separate table). Though I have done similar things in other RDBMs using SQL, I find doing this in Postgres, a little bit complicated - may be because it needs to be done through a separate procedural language and through a separate function. The Postgres documentation also didn't provide much help ( the examples in C). I was mainly looking for example showing how to refer 'OLD' and 'NEW' rows using PL/pgSQL. Can someone please direct me to some such examples? How about this: CREATE TABLE my_table ( my_table_id BIGSERIAL NOT NULL, my_value VARCHAR(100) NOT NULL, CONSTRAINT my_table_pkey PRIMARY KEY (my_table_id) ); CREATE TABLE my_table_history ( my_table_id BIGINT NOT NULL, my_value VARCHAR(100) NOT NULL, create_dt TIMESTAMP NOT NULL, CONSTRAINT my_table_history_pkey PRIMARY KEY (my_table_id, create_dt) ); CREATE OR REPLACE FUNCTION my_table_history_fn () RETURNS SETOF opaque AS ' BEGIN -- if a trigger insert or update operation occurs IF TG_OP = ''INSERT'' OR TG_OP = ''UPDATE'' THEN execute ''INSERT INTO my_table_history ( '' || '' my_table_id, '' || '' my_value, '' || '' create_dt '' || '') VALUES ( '' || '' '''''' || NEW.my_table_id || '''''', '' || '' '''''' || NEW.my_value || '''''', '' || '' now() '' || '');'' ; RETURN NEW; END IF; END; ' LANGUAGE 'plpgsql' VOLATILE CALLED ON NULL INPUT SECURITY INVOKER; CREATE TRIGGER my_table_history_tr BEFORE UPDATE OR INSERT ON my_table FOR EACH ROW EXECUTE PROCEDURE my_table_history_fn(); I tried it out and it works in version 8.1. ================================================================== Aaron Bono Aranya Software Technologies, Inc. http://www.aranya.com ================================================================== --0-715009522-1154323857=:24141 Content-Type: text/html; charset=iso-8859-1 Content-Transfer-Encoding: 8bit Hello,

Thanks a lot Aaron for the very quick and simple example. I just checked it on 7.4.5 also and it worked. I'll be able to continue with my development using  the syntax of that example.

Regards,
-Thusitha

Aaron Bono <postgresql@aranya.com> wrote:
On 7/30/06, Thusitha Kodikara <kthusi@yahoo.com> wrote:
Hello,

I am interested in developing some triggers to keep track of records that are changed (possibly the changes of one or more specific columns). In addition to keeping the new values, I also need to keep the old values (may be on a separate table). 

Though I  have done similar things in other RDBMs using SQL, I find doing this in Postgres, a little bit complicated - may be because it needs to be done through a separate procedural language and through a separate function. The Postgres documentation also didn't provide much help ( the examples in C). I was mainly looking for example showing how to refer 'OLD' and 'NEW' rows using PL/pgSQL.

Can someone please direct me to some such examples?

 
How about this:

CREATE TABLE my_table (
   my_table_id BIGSERIAL NOT NULL,
   my_value VARCHAR(100) NOT NULL,
   CONSTRAINT my_table_pkey PRIMARY KEY (my_table_id)
);

CREATE TABLE my_table_history (
   my_table_id BIGINT NOT NULL,
   my_value VARCHAR(100) NOT NULL,
   create_dt TIMESTAMP NOT NULL,
   CONSTRAINT my_table_history_pkey PRIMARY KEY (my_table_id, create_dt)
);

CREATE OR REPLACE FUNCTION my_table_history_fn () RETURNS SETOF opaque AS
'
BEGIN
    -- if a trigger insert or update operation occurs
    IF TG_OP = ''INSERT'' OR TG_OP = ''UPDATE'' THEN
        execute
            ''INSERT INTO my_table_history ( '' ||
            ''    my_table_id, '' ||
            ''    my_value, '' ||
            ''    create_dt '' ||
            '') VALUES ( '' ||
            ''    '''''' || NEW.my_table_id || '''''', '' ||
            ''    '''''' || NEW.my_value || '''''', '' ||
            ''    now() '' ||
            '');''
        ;
        RETURN NEW;
    END IF;
END;
'
LANGUAGE 'plpgsql' VOLATILE CALLED ON NULL INPUT SECURITY INVOKER;

CREATE TRIGGER my_table_history_tr BEFORE UPDATE OR INSERT
    ON my_table FOR EACH ROW
    EXECUTE PROCEDURE my_table_history_fn();

I tried it out and it works in version 8.1.

==================================================================
   Aaron Bono
   Aranya Software Technologies, Inc.
   http://www.aranya.com
==================================================================

--0-715009522-1154323857=:24141--