Thread: Re: INSERT OR UPDATE?
smorrey@gmail.com writes: > Hello all, > > I am writing an app in PHP that uses a PostGres database. > One thing i have noticed is that what should/could be a single line of > SQL code takes about 6 lines of PHP. This seem wasteful and redundant > to me. Here ya go!... create temp table foo ( id int primary key, data text ); create rule foo as on insert to foo where exists ( select 1 from foo where id = new.id ) do instead update foo set data = new.data where id = new.id ; copy foo from stdin using delimiters ','; 1,hello 2,hello \. select * from foo order by id; insert into foo values ( 1,'it works!' ); select * from foo order by id; Outout... CREATE TABLE CREATE RULE id | data ----+------- 1 | hello 2 | hello (2 rows) INSERT 0 0 id | data ----+----------- 1 | it works! 2 | hello (2 rows) HTH -- ------------------------------------------------------------------------------- Jerry Sievers 305 854-3001 (home) WWW ECommerce Consultant 305 321-1144 (mobile http://www.JerrySievers.com/
On Sun, Oct 09, 2005 at 10:10:28AM -0400, Jerry Sievers wrote: > smorrey@gmail.com writes: > > > Hello all, > > > > I am writing an app in PHP that uses a PostGres database. One > > thing i have noticed is that what should/could be a single line of > > SQL code takes about 6 lines of PHP. This seem wasteful and > > redundant to me. > > Here ya go!... > > create temp table foo ( > id int primary key, > data text > ); > > create rule foo > as on insert to foo > where exists ( > select 1 > from foo > where id = new.id > ) > do instead > update foo > set data = new.data > where id = new.id > ; This is very clever, but it has a race condition. What happens if between the time of the EXISTS() check and the start of the UPDATE, something happens to that row? Similarly, what if a row comes into existence between the EXISTS() check and the INSERT? The UPSERT example below, while a little more complicated to write and use, handles this. http://developer.postgresql.org/docs/postgres/plpgsql-control-structures.html#PLPGSQL-ERROR-TRAPPING SQL:2003 standard MERGE should fix all this. Cheers, D -- David Fetter david@fetter.org http://fetter.org/ phone: +1 510 893 6100 mobile: +1 415 235 3778 Remember to vote!
Actually I think the uniqueness constraint (due to the primary key) is the one handling it. There's nothing special about that function that will prevent duplicates. Try running it without the primary key specifications in two separate concurrent transactions. Then commit both transactions. Similarly the other methods will be fine as long as there is a uniqueness constraint. If you don't have a uniqueness constraint or you don't want to trigger and exception/error (which could be troublesome in versions of Postgresql without savepoints) then you will have to use locking. It's actually quite surprising how many people get this wrong and don't realize it (I wonder how many problems are because of this). The SQL spec should have had a PUT/MERGE decades ago. The insert vs update format being different is also annoying, oh well. Regards, Link. At 10:01 AM 10/9/2005 -0700, David Fetter wrote: >This is very clever, but it has a race condition. What happens if >between the time of the EXISTS() check and the start of the UPDATE, >something happens to that row? Similarly, what if a row comes into >existence between the EXISTS() check and the INSERT? > >The UPSERT example below, while a little more complicated to write and >use, handles this. > >http://developer.postgresql.org/docs/postgres/plpgsql-control-structures.html#PLPGSQL-ERROR-TRAPPING > >SQL:2003 standard MERGE should fix all this. > >Cheers, >D >-- >David Fetter david@fetter.org http://fetter.org/ >phone: +1 510 893 6100 mobile: +1 415 235 3778 > >Remember to vote! > >---------------------------(end of broadcast)--------------------------- >TIP 5: don't forget to increase your free space map settings
On Mon, 2005-10-10 at 13:34, Lincoln Yeoh wrote: [snip] > It's actually quite surprising how many people get this wrong and don't > realize it (I wonder how many problems are because of this). The SQL spec > should have had a PUT/MERGE decades ago. The insert vs update format being > different is also annoying, oh well. Referring to the above, is there any plan to implement such commands in postgres ? I don't know if it is standard SQL, but some other RDBMSes have such command, and they are actually useful. > > Regards, > Link. [snip] Cheers, Csaba.
Check the TODO, I'm 99% certain it's on there. On Mon, Oct 10, 2005 at 02:02:32PM +0200, Csaba Nagy wrote: > On Mon, 2005-10-10 at 13:34, Lincoln Yeoh wrote: > [snip] > > It's actually quite surprising how many people get this wrong and don't > > realize it (I wonder how many problems are because of this). The SQL spec > > should have had a PUT/MERGE decades ago. The insert vs update format being > > different is also annoying, oh well. > > Referring to the above, is there any plan to implement such commands in > postgres ? I don't know if it is standard SQL, but some other RDBMSes > have such command, and they are actually useful. > > > > > Regards, > > Link. > [snip] > > Cheers, > Csaba. > > > > ---------------------------(end of broadcast)--------------------------- > TIP 3: Have you checked our extensive FAQ? > > http://www.postgresql.org/docs/faq > -- Jim C. Nasby, Sr. Engineering Consultant jnasby@pervasive.com Pervasive Software http://pervasive.com work: 512-231-6117 vcard: http://jim.nasby.net/pervasive.vcf cell: 512-569-9461