Thread: Creating Functions & Triggers
Hello everyone, I'm new to creating functions & triggers on postgresql and am having trouble creating a trigger to update a record with the modification date and the current user. My code is below, but doesn't work. It hangs psql when I attempt to modify the record. The function and trigger are created successfully. CREATE FUNCTION email_mod_date() RETURNS OPAQUE AS ' BEGIN UPDATE email SET m_date = current_date, m_by_user = current_user WHERE id = NEW.id; RETURN NULL; END; 'LANGUAGE 'plpgsql'; CREATE TRIGGER email_mod_date AFTER UPDATE ON email FOR EACH ROW EXECUTE PROCEDURE email_mod_date(); Thanks for any help. Kevin Lohka
Re: Creating Functions & Triggers
From
"V i s h a l Kashyap @ [Sai Hertz And Control Systems]"
Date:
Dear Kevin , > CREATE FUNCTION email_mod_date() RETURNS OPAQUE AS ' > BEGIN > UPDATE email SET m_date = current_date, m_by_user = current_user > WHERE id = NEW.id; > > RETURN NULL; > END; > 'LANGUAGE 'plpgsql'; CREATE FUNCTION email_mod_date() RETURNS OPAQUE AS ' DECLARE BEGIN UPDATE email SET m_date = current_date, m_by_user = current_user WHERE id = NEW.id; RETURN NEW; END; 'LANGUAGE 'plpgsql'; This must do the job. But why you need a trigger for all this. Just use a default value for the respective column's . -- Best Regards, Vishal Kashyap Director / Lead Developer, Sai Hertz And Control Systems Pvt Ltd, http://saihertz.rediffblogs.com Jabber IM: vishalkashyap@jabber.org ICQ : 264360076 Yahoo IM: mailforvishal@yahoo.com ----------------------------------------------- You yourself, as much as anybody in the entire universe, deserve your love and affection. - Buddha --------------- pgsql=# select marital_status from vishals_life; marital_status ------------------ Single not looking 1 Row(s) affected ___ //\\\ ( 0_0 ) ----------------o0o-----o0o---------------------
Re: Creating Functions & Triggers
From
"V i s h a l Kashyap @ [Sai Hertz And Control Systems]"
Date:
Dear Kevin , >> CREATE FUNCTION email_mod_date() RETURNS TRIGGER AS ' >> DECLARE >> BEGIN >> UPDATE email SET m_date = current_date, m_by_user = current_user >> WHERE id = NEW.id; >> >> RETURN NEW; >> END; >> 'LANGUAGE 'plpgsql'; >> >> This must do the job. > > > Thanks for the suggestion, unfortunately it still hangs when I try and > update a record. > >> But why you need a trigger for all this. >> >> Just use a default value for the respective column's . > > > Isn't the default value only used during the initial insert of a > record? How would I set the default value for an UPDATE only? Yes, you can set the default value for update of a record just with UPDATE email SET m_date = DEFAULT, m_by_user = DEFAULT WHERE id = some_id; I am doing this thing in PostgreSQL 7.4.2 > > Sorry for the basic questions, but I'm quite new to this. Its ok, read above Kindly pas on the query you are issuing . -- Best Regards, Vishal Kashyap Director / Lead Developer, Sai Hertz And Control Systems Pvt Ltd, http://saihertz.rediffblogs.com Jabber IM: vishalkashyap@jabber.org ICQ : 264360076 Yahoo IM: mailforvishal@yahoo.com ----------------------------------------------- You yourself, as much as anybody in the entire universe, deserve your love and affection. - Buddha --------------- pgsql=# select marital_status from vishals_life; marital_status ------------------ Single not looking 1 Row(s) affected ___ //\\\ ( 0_0 ) ----------------o0o-----o0o---------------------
On Saturday, March 20, 2004, at 09:08 PM, V i s h a l Kashyap @ [Sai Hertz And Control Systems] wrote: >> >> >>> But why you need a trigger for all this. >>> >>> Just use a default value for the respective column's . >> >> >> Isn't the default value only used during the initial insert of a >> record? How would I set the default value for an UPDATE only? > > Yes, you can set the default value for update of a record > just with > > UPDATE email SET m_date = DEFAULT, m_by_user = DEFAULT WHERE id = > some_id; If I use this method, I will need to control the input from the client side. I was hoping to have an easy way to update the record with the last date modified and user who modified the record regardless of where the modification came from. eg. Web or internal client software. > > I am doing this thing in PostgreSQL 7.4.2 I'm using PostgreSQL 7.4.1 on Mac OS X 10.2.8 > > Kindly pas on the query you are issuing . > acc=# UPDATE email SET email_address = 'mynewusername@mydomain.com' WHERE id = 14; ------------- UPDATE 1 Thank you for your time Vishal. Kevin Lohka
Re: Creating Functions & Triggers
From
"V i s h a l Kashyap @ [Sai Hertz And Control Systems]"
Date:
Dear Kevin , >> >> Yes, you can set the default value for update of a record >> just with >> >> UPDATE email SET m_date = DEFAULT, m_by_user = DEFAULT WHERE id = >> some_id; > > > If I use this method, I will need to control the input from the client > side. I was hoping to have an easy way to update the record with the > last date modified and user who modified the record regardless of > where the modification came from. eg. Web or internal client software. If the below query is issed by the web client then your job could be done by the said above query as well . To my limited knowledge no need to write a trigger. Just try using this CREATE FUNCTION email_mod_date() RETURNS TRIGGER AS ^^^^^^^^ >> > > acc=# UPDATE email SET email_address = 'mynewusername@mydomain.com' > WHERE id = 14; > ------------- > UPDATE 1 I suppose this is update has been done without the trigger in place. To my limited knowledge is the trigger going into a sort of race condition > > Thank you for your time Vishal. Oh!, Its my pleaseure. But kindly pass on the solution if you have found one. -- Best Regards, Vishal Kashyap Director / Lead Developer, Sai Hertz And Control Systems Pvt Ltd, http://saihertz.rediffblogs.com Jabber IM: vishalkashyap@jabber.org ICQ : 264360076 Yahoo IM: mailforvishal@yahoo.com ----------------------------------------------- You yourself, as much as anybody in the entire universe, deserve your love and affection. - Buddha --------------- pgsql=# select marital_status from vishals_life; marital_status ------------------ Single not looking 1 Row(s) affected ___ //\\\ ( 0_0 ) ----------------o0o-----o0o---------------------
On Saturday, March 20, 2004, at 10:23 PM, V i s h a l Kashyap @ [Sai Hertz And Control Systems] wrote: > Dear Kevin , > >>> >>> Yes, you can set the default value for update of a record >>> just with >>> >>> UPDATE email SET m_date = DEFAULT, m_by_user = DEFAULT WHERE id = >>> some_id; >> >> >> If I use this method, I will need to control the input from the >> client side. I was hoping to have an easy way to update the record >> with the last date modified and user who modified the record >> regardless of where the modification came from. eg. Web or internal >> client software. > > If the below query is issed by the web client then your job could be > done by the said above query as well . > To my limited knowledge no need to write a trigger. > Just try using this > > CREATE FUNCTION email_mod_date() RETURNS TRIGGER AS > > ^^^^^^^^ I'll give it a try. >>> >> >> acc=# UPDATE email SET email_address = 'mynewusername@mydomain.com' >> WHERE id = 14; >> ------------- >> UPDATE 1 > > I suppose this is update has been done without the trigger in place. That's correct, when the function & trigger are in place psql just hangs. It does not accept any input and the only way I know how to terminate the process is to restart postmaster from another process. > > But kindly pass on the solution if you have found one. > > As soon as I find one I will. I'm sure that I just have a simple syntax error, but I'm too new to know what it is. Kevin Lohka
В Сбт, 20.03.2004, в 23:33, Kevin Lohka пишет: > Hello everyone, I'm new to creating functions & triggers on postgresql > and am having trouble creating a trigger to update a record with the > modification date and the current user. > > My code is below, but doesn't work. It hangs psql when I attempt to > modify the record. The function and trigger are created successfully. > > CREATE FUNCTION email_mod_date() RETURNS OPAQUE AS ' > BEGIN > UPDATE email SET m_date = current_date, m_by_user = > current_user > WHERE id = NEW.id; > > RETURN NULL; > END; > 'LANGUAGE 'plpgsql'; > > > > CREATE TRIGGER email_mod_date > AFTER UPDATE > ON email > FOR EACH ROW > EXECUTE PROCEDURE email_mod_date(); The trigger is probably recursively being called. http://www.postgresql.org/docs/current/static/triggers.html#TRIGGER-DEFINITION -- Markus Bertheau <twanger@bluetwanger.de>
Markus Bertheau <twanger@bluetwanger.de> writes: > The trigger is probably recursively being called. Well, of course. Every UPDATE causes another UPDATE, which queues another trigger firing. What else would you expect but an infinite loop? The correct way to do this is illustrated in the plpgsql trigger example at the bottom of this page: http://www.postgresql.org/docs/7.4/static/plpgsql-trigger.html You use a BEFORE trigger and alter the NEW record before it gets written. AFTER triggers are not intended for modifying data in the record they are fired for --- it's too late for that. (Even if you avoid the infinite loop by testing whether you really need to do another UPDATE or not, it's still ridiculously inefficient to force another cycle of UPDATE when you could just as easily have gotten it right beforehand.) Usually people use AFTER triggers for end-of-command consistency checking or for propagating information to other tables. regards, tom lane
Thanks for the help Tom & Markus I've got it now. Kevin Lohka On Sunday, March 21, 2004, at 09:18 AM, Tom Lane wrote: > Markus Bertheau <twanger@bluetwanger.de> writes: >> The trigger is probably recursively being called. > > Well, of course. Every UPDATE causes another UPDATE, which queues > another trigger firing. What else would you expect but an infinite > loop? > > The correct way to do this is illustrated in the plpgsql trigger > example at the bottom of this page: > http://www.postgresql.org/docs/7.4/static/plpgsql-trigger.html > You use a BEFORE trigger and alter the NEW record before it gets > written. > > AFTER triggers are not intended for modifying data in the record they > are fired for --- it's too late for that. (Even if you avoid the > infinite loop by testing whether you really need to do another UPDATE > or not, it's still ridiculously inefficient to force another cycle of > UPDATE when you could just as easily have gotten it right beforehand.) > Usually people use AFTER triggers for end-of-command consistency > checking or for propagating information to other tables. > > regards, tom lane
On Sun, Mar 21, 2004 at 10:21:57AM -0700, Kevin Lohka wrote: > Thanks for the help Tom & Markus I've got it now. so did I so here is my version: drop table email; drop trigger email_mod_date; drop function email_mod_date(); create table email ( id serial not null primary key, email character varying(100), name character varying(100), m_date date, m_by_user character varying(100)); CREATE FUNCTION email_mod_date() RETURNS OPAQUE AS ' BEGIN new.m_date = current_date; new.m_by_user = current_user; RETURN new; END; 'LANGUAGE 'plpgsql'; CREATE TRIGGER email_mod_date_trigger BEFORE UPDATE ON email FOR EACH ROW EXECUTE PROCEDURE email_mod_date(); insert into email (email,name) values ('email1','name1'); insert into email (email,name) values ('email2','name2'); insert into email (email,name) values ('email3','name3'); select * from email; update email set email='email1_new' where name='name1'; select * from email; > > Kevin Lohka > > On Sunday, March 21, 2004, at 09:18 AM, Tom Lane wrote: > > >Markus Bertheau <twanger@bluetwanger.de> writes: > >>The trigger is probably recursively being called. > > > >Well, of course. Every UPDATE causes another UPDATE, which queues > >another trigger firing. What else would you expect but an infinite > >loop? > > > >The correct way to do this is illustrated in the plpgsql trigger > >example at the bottom of this page: > >http://www.postgresql.org/docs/7.4/static/plpgsql-trigger.html > >You use a BEFORE trigger and alter the NEW record before it gets > >written. > > > >AFTER triggers are not intended for modifying data in the record they > >are fired for --- it's too late for that. (Even if you avoid the > >infinite loop by testing whether you really need to do another UPDATE > >or not, it's still ridiculously inefficient to force another cycle of > >UPDATE when you could just as easily have gotten it right beforehand.) > >Usually people use AFTER triggers for end-of-command consistency > >checking or for propagating information to other tables. > > > > regards, tom lane > > > ---------------------------(end of broadcast)--------------------------- > TIP 4: Don't 'kill -9' the postmaster -- joe speigle www.sirfsup.com