如何在postgres数据库上切换两个ID [PK]?

时间:2012-04-05 13:39:07

标签: sql postgresql

我想更改Postgres上两行的ID,以切换它们。它们已被定义为外键,因此我无法使用第三个数字进行切换。

如何在一个SQL查询或事务中执行此操作?

示例:

UPDATE mytable SET id=2 WHERE ID=1;
UPDATE mytable SET id=1 WHERE ID=2

3 个答案:

答案 0 :(得分:4)

您提到外键,但仍不清楚id是外键约束的引用列还是引用列。

如果 id是引用列,则只需定义fk约束ON UPDATE CASCADE。然后,您可以根据需要更改id。更改会级联到相关列。


如果 id是引用列(没有其他外键约束指向它),那么自 PostgreSQL 9.0 以来还有另一种更快的方法。您可以使用可延迟的主键或唯一键。请考虑以下演示:

注意如果您想从另一个表中引用带有外键约束的id,则无法使用此功能。我引用手册here

  

引用的列必须是不可延迟的唯一列   或引用表中的主键约束。

试验台:

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 t
SET    id = t_old.id
FROM   t t_old
WHERE (t.id, t_old.id) IN ((1,2), (2,1));

结果:

SELECT * FROM t; 

id | txt
---+-----
2  | one
1  | two

您还可以在同一交易中声明约束DEFERRABLE INITIALLY IMMEDIATE并使用SET CONSTRAINTS ... DEFERRED

请务必阅读手册中的详细信息:


甚至似乎与DEFERRABLE INITIALLY IMMEDIATESET CONSTRAINTS一起使用。我发布了question about that

答案 1 :(得分:1)

你有没有试过像:

BEGIN;

CREATE TEMP TABLE updates ON COMMIT DROP AS
SELECT column1::int oldid, column2::int newid
FROM ( VALUES (1, 2), (2, 1) ) foo;

UPDATE mytable
FROM updates
SET id = newid
WHERE id = oldid;

--COMMIT;
ROLLBACK;

当然,当您准备好时,回滚会被注释掉并提交。

答案 2 :(得分:0)

begin;
alter table mytable drop constraint_name;
UPDATE mytable SET id=-1 WHERE ID=1;
UPDATE mytable SET id=1 WHERE ID=2;
UPDATE mytable SET id=2 WHERE ID=-1;
alter table mytable add table_constraint;
commit;