Received: from localhost (maia-4.hub.org [200.46.204.183]) by postgresql.org (Postfix) with ESMTP id F2E199FB504 for ; Thu, 19 Apr 2007 15:55:31 -0300 (ADT) Received: from postgresql.org ([200.46.204.71]) by localhost (mx1.hub.org [200.46.204.183]) (amavisd-maia, port 10024) with ESMTP id 80555-01 for ; Thu, 19 Apr 2007 15:55:28 -0300 (ADT) X-Greylist: from auto-whitelisted by SQLgrey-1.7.4 Received: from main2.mycybernet.net (main2.mycybernet.net [209.222.63.140]) by postgresql.org (Postfix) with ESMTP id 1B19B9FB349 for ; Thu, 19 Apr 2007 15:55:27 -0300 (ADT) Received: from 227-54-222-209.mycybernet.net ([209.222.54.227] helo=phlogiston.dydns.org) by main2.mycybernet.net with esmtp (Exim 4.62) (envelope-from ) id 1Hebmx-0004ME-2H for pgsql-sql@postgresql.org; Thu, 19 Apr 2007 14:55:27 -0400 Received: by phlogiston.dydns.org (Postfix, from userid 1000) id 987FB4050; Thu, 19 Apr 2007 14:55:21 -0400 (EDT) Date: Thu, 19 Apr 2007 14:55:21 -0400 From: Andrew Sullivan To: pgsql-sql@postgresql.org Subject: Re: Doing a conditional insert/update Message-ID: <20070419185521.GB14821@phlogiston.dyndns.org> References: <978075550704191127g781a4a26i400f4fc80d491df6@mail.gmail.com> Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <978075550704191127g781a4a26i400f4fc80d491df6@mail.gmail.com> User-Agent: Mutt/1.5.9i X-Virus-Scanned: Maia Mailguard 1.0.1 X-Archive-Number: 200704/167 X-Sequence-Number: 28167 On Thu, Apr 19, 2007 at 08:27:30PM +0200, Markus Holzer wrote: > How do I perform a conditional insert/update? The short answer is that you can't, at least not the way you want to. > already in the table, or an update if it is. I have currently solved this by > SELECTing for the primary key, then looking if there is a row, and if there > is I do an UPDATE otherwise I do an INSERT. But since this is a web app this > way of course leaves a big race condition. Only if you don't do it in one transaction. If you use a savepoint to do this, then you can BEGIN, SELECT FOR UPDATE, then if you get it UPDATE; if you don't, start a savepoint, insert, and if you don't get a failure, commit the whole thing. If you _do_ get a failure, you rollback the savepoint, and then do the update. There's a (cleaner) example of this in the UPDATE doc from the 8.2 release. But I have doubts that your program design is right if this is the approach you're trying to take (it's not impossible that it's the right way, just that this is often a workaround for a dodgy data model in the first place). What is the conflict you're trying to avoid? A -- Andrew Sullivan | ajs@crankycanuck.ca The fact that technology doesn't work is no bar to success in the marketplace. --Philip Greenspun