Received: from localhost (unknown [200.46.208.211]) by mail.postgresql.org (Postfix) with ESMTP id 1DB72633212 for ; Mon, 13 Apr 2009 13:53:57 -0300 (ADT) Received: from mail.postgresql.org ([200.46.204.86]) by localhost (mx1.hub.org [200.46.208.211]) (amavisd-maia, port 10024) with ESMTP id 58658-01 for ; Mon, 13 Apr 2009 13:53:53 -0300 (ADT) X-Greylist: from auto-whitelisted by SQLgrey-1.7.6 Received: from mailproxy.safepages.com (mailproxy.safepages.com [216.126.204.70]) by mail.postgresql.org (Postfix) with ESMTP id 12145632A9A for ; Mon, 13 Apr 2009 13:53:54 -0300 (ADT) Received: from kyoto.home (5131-133-241.239.popsite.net [64.24.133.241]) by mailproxy.safepages.com (Postfix) with ESMTP id 88C74177511 for ; Mon, 13 Apr 2009 10:53:50 -0600 (MDT) Received: from kyoto.home (kyoto.home [127.0.0.1]) by kyoto.home (Postfix) with ESMTP id 563C745EFA6 for ; Mon, 13 Apr 2009 10:53:48 -0600 (MDT) Message-ID: <49E36E1B.6020107@frii.com> Date: Mon, 13 Apr 2009 10:53:47 -0600 From: Stuart McGraw User-Agent: Thunderbird 2.0.0.19 (X11/20090105) MIME-Version: 1.0 To: pgsql-sql@postgresql.org Subject: Re: changing multiple pk's in one update References: <49DC1034.1060705@frii.com> In-Reply-To: Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit X-Virus-Scanned: Maia Mailguard 1.0.1 X-Spam-Status: No, hits=0 tagged_above=0 required=5 tests=none X-Spam-Level: X-Archive-Number: 200904/59 X-Sequence-Number: 32405 Jasen Betts wrote: > On 2009-04-08, Stuart McGraw wrote: >> Hello all, >> >> I have a table with a primary key column >> that contains sequential numbers. >> >> Sometimes I need to shift them all up or down >> by a fixed amount. For example, if I have >> four rows with primary keys, 2, 3, 4, 5, I >> might want to shift them down by 1 by doing: >> >> UPDATE mytable SET id=id-1 >> >> (where "id" is the pk column) so that the pk's >> are now 1, 2, 3, 4. >> >> When I try to shift them up by using +1 in the >> above update statement, I get (not surprisingly) >> a duplicate key error. I also realize that the >> -1 case above works only by luck. >> >> So my question: >> Is there some way, perhaps with ORDER BY, that >> I can achieve the change I want with a single >> update statement? (If I have an unused key >> range large enough, I suppose I could update >> all the keys to that range, and then back to >> my target range but the requires two updates >> (there are a lot of foreign keys referencing >> these primary keys) and requires that I have >> an available range, so a single update statement >> would be preferable.) >> >> Thanks for any enlightenment. > > begin a transaction > suspend the constraint (use SET CONSTRAINTS ... DEFERRED) > drop the index > do the update(s) > recreate the index > commit the transaction. > > I see no reason to keep the index (and its associated UNIQUE > constraint) during the update, AFAICT all it does is slow the process > down. Thanks for the suggestion. Unfortunately I am doing this key renumbering in an interactive gui app and as there are several million rows involved, rebuilding indexes take too long. I have continued searching for other ways to do this but most of my google results are floating in a sea of "update if insert fails, like mysql" results so I still have a little hope it is possible. I thought I remember seeing, a year or two ago, an update statement with an ordered subquery that avoided duplicate key errors but I am probably misrembering.