PostgreSQL:具有唯一索引的批量更新

时间:2017-04-23 17:55:47

标签: postgresql

我有两个字段的唯一索引表,lane_id和position。

现在,我想使用此查询更新行:

UPDATE "teams_ticket" SET "position" = ("teams_ticket"."position" + 1) WHERE ("teams_ticket"."lane_id" = 1 AND "teams_ticket"."position" >= 0)

最终:

duplicate key value violates unique constraint "teams_ticket_position_bfcce9fa_uniq"

如果我有一张以上的票。

我该如何解决这个问题?

3 个答案:

答案 0 :(得分:0)

您可以使用游标逐个更新它们。

DO $$
  DECLARE r record;
BEGIN
  FOR r IN SELECT lane_id, position FROM teams_ticket WHERE lane_id=1 AND position >= 0 ORDER BY position DESC
  LOOP
    UPDATE teams_ticket SET position=position+1 WHERE position=r.position AND lane_id=r.lane_id;
  END LOOP;
END$$;

答案 1 :(得分:0)

您需要deferrable个约束(实际上是暂时推迟)。 Deferrable意味着不会立即检查约束(例如:在重写索引元组时),但在事务(或语句)结束时,所有行都已更新:

- \ t tmp.sql

CREATE TABLE positions
        ( seq SERIAL PRIMARY KEY
        , position INTEGER NOT NULL UNIQUE DEFERRABLE 
        );

INSERT INTO positions(position)
SELECT generate_series(1,10) gs;

BEGIN;
SET CONSTRAINTS ALL DEFERRED;

update positions
SET position= position +1
WHERE seq <= 6 ;

SELECT * FROM positions ;

UPDATE positions SET position= position +1
WHERE seq > 6
        ;

SELECT * FROM positions ;

UPDATE positions SET position= position +1
        ;

SELECT * FROM positions ;

COMMIT;

答案 2 :(得分:-1)

你可以尝试

UPDATE teams_ticket t
   SET position = q.position + 1
  FROM (
    SELECT lane_id, position
      FROM teams_ticket
     WHERE lane_id = 1 
       AND position >= 0
     ORDER BY lane_id, position DESC
  ) q 
  WHERE t.lane_id = q.lane_id
    AND t.position = q.position