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 24BB89FB346 for ; Mon, 31 Jul 2006 02:35:15 -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 47021-08 for ; Mon, 31 Jul 2006 02:35:11 -0300 (ADT) X-Greylist: domain auto-whitelisted by SQLgrey- Received: from nf-out-0910.google.com (nf-out-0910.google.com [64.233.182.190]) by postgresql.org (Postfix) with ESMTP id DE0C99FB343 for ; Mon, 31 Jul 2006 02:34:40 -0300 (ADT) Received: by nf-out-0910.google.com with SMTP id p77so384424nfc for ; Sun, 30 Jul 2006 22:34:39 -0700 (PDT) DomainKey-Signature: a=rsa-sha1; q=dns; c=nofws; s=beta; d=gmail.com; h=received:message-id:date:from:sender:to:subject:cc:in-reply-to:mime-version:content-type:references:x-google-sender-auth; b=Y1w8M0OpF9oX2QZY/8kE4/PsFRj2wgSVCU56ezpjTUcnO0+z4hNQ30U6H677ZSFGezQhAdI3Q8qmjFVDAuKvhemVLt5DegdOan1X31xYuCARLG20EDuC8gguKC3Pdf3EDKne6RuC1lxv8MLRllsDoni2oAEWoXGDGDyv/fDmUYo= Received: by 10.78.120.6 with SMTP id s6mr413574huc; Sun, 30 Jul 2006 22:34:39 -0700 (PDT) Received: by 10.78.32.10 with HTTP; Sun, 30 Jul 2006 22:34:38 -0700 (PDT) Message-ID: Date: Mon, 31 Jul 2006 00:34:38 -0500 From: "Aaron Bono" To: "Thusitha Kodikara" Subject: Re: Triggers using PL/pgSQL Cc: pgsql-sql@postgresql.org In-Reply-To: <20060731053057.28266.qmail@web56612.mail.re3.yahoo.com> MIME-Version: 1.0 Content-Type: multipart/alternative; boundary="----=_Part_39169_25612059.1154324078919" References: <20060731053057.28266.qmail@web56612.mail.re3.yahoo.com> X-Google-Sender-Auth: f98d3671a9514113 X-Virus-Scanned: Maia Mailguard 1.0.1 X-Spam-Status: No, hits=0.609 tagged_above=0 required=5 tests=AWL, DNS_FROM_RFC_ABUSE, HTML_40_50, HTML_MESSAGE, SPF_PASS X-Spam-Level: X-Archive-Number: 200607/371 X-Sequence-Number: 25945 ------=_Part_39169_25612059.1154324078919 Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit Content-Disposition: inline No problem. I have been meaning to put the same code together for myself but have been putting it off. It gave me an excuse to stop procrastinating. On 7/31/06, Thusitha Kodikara wrote: > > 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. > *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 ================================================================== ------=_Part_39169_25612059.1154324078919 Content-Type: text/html; charset=ISO-8859-1 Content-Transfer-Encoding: 7bit Content-Disposition: inline No problem.  I have been meaning to put the same code together for myself but have been putting it off.  It gave me an excuse to stop procrastinating.

On 7/31/06, Thusitha Kodikara <kthusi@yahoo.com> wrote:
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.
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
================================================================== ------=_Part_39169_25612059.1154324078919--