You mention foreign keys, but it remains unclear whether id
is the referenced or the referencing column of a foreign key constraint.
If id
is the referenced column you just define the fk constraint ON UPDATE CASCADE
. Then you can change your id
as much as you want. Changes are cascaded to the depending columns.
If id
is the referencing column (and no other foreign key constraints point to it), then there is another, faster way since PostgreSQL 9.0. You can use a deferrable primary or unique key. Consider the following demo:
Note that you can't use this if you want to reference id
with a foreign key constraint from another table. I quote the manual here:
The referenced columns must be the columns of a non-deferrable unique
or primary key constraint in the referenced table.
Testbed:
CREATE TEMP TABLE t
( id integer
,txt text
,CONSTRAINT t_pkey PRIMARY KEY (id) DEFERRABLE INITIALLY DEFERRED
);
INSERT INTO t VALUES
(1, 'one')
,(2, 'two');
Update:
UPDATE t
SET id = t_old.id
FROM t t_old
WHERE (t.id, t_old.id) IN ((1,2), (2,1));
Result:
SELECT * FROM t;
id | txt
---+-----
2 | one
1 | two
You can also declare the constraint DEFERRABLE INITIALLY IMMEDIATE
and use SET CONSTRAINTS ... DEFERRED
in the same transaction.
Be sure to read about the details in the manual:
Even seems to work with DEFERRABLE INITIALLY IMMEDIATE
and no SET CONSTRAINTS
. I posted a question about that.