UNIQUE
约束的特定列,某些表的记录中的交换值。
考虑下表:
CREATE TABLE records (id numeric, name text);
ALTER TABLE records ADD CONSTRAINT uniq UNIQUE (id);
INSERT INTO records VALUES
(1, 'First record'),
(3, 'Second record'),
(2, 'Third record'),
(4, 'Fourth record');
我们从查询SELECT id, name FROM records ORDER BY id;
:
| id | name |
|----|---------------|
| 1 | First record |
| 2 | Third record |
| 3 | Second record |
| 4 | Fourth record |
id
和Second record
已交换需要Third record
秒。也就是说,我想要以下输出:
| id | name |
|----|---------------|
| 1 | First record |
| 2 | Second record | <-- this record previously had the id 3
| 3 | Third record | <-- this record previously had the id 2
| 4 | Fourth record |
name
,我的实际数据库比这个大一点:
id
列实际上是其他表引用的PRIMARY KEY
。id
来执行此交换。id
始终都是唯一的id
将与新作业地图重叠。我尝试通过生成临时重新分配表并在UPDATE ... SET ... FROM ... WHERE
查询中使用它来在单个查询中交换我的数据。
这是我的临时重新分配表,它将交换id
s 2
和3
:
(VALUES
(3, 2),
(2, 3)
) AS swap(id, new_id)
以下是我如何使用它:
UPDATE records AS record SET
id = swap.new_id
FROM (VALUES
(3, 2),
(2, 3)
) AS swap(id, new_id)
WHERE record.id = swap.id;
SELECT id, name FROM records ORDER BY id;
正如您在SQLFiddle link中看到的那样,它很有效......直到您在UNIQUE
列上添加id
约束。
我怎样才能在上面列出的所有条件下工作?
答案 0 :(得分:7)
问题在于CONSTRAINT
的定义。
PosgreSQL &#39; CONSTRAINTS
可以是DEFERRABLE
。从their documentation开始,我们收集以下内容:
在每个语句的末尾检查IMMEDIATE约束。在事务提交之前不会检查DEFERRED约束。每个约束都有自己的IMMEDIATE或DEFERRED模式。
在我们面临的情况下,id
仍然是UNIQUE
s AFTER 交易,而CONSTRAINT
确实不能满意 DURING 重新分配id
s。
只需制作相关的CONSTRAINT
DEFERRABLE
即可解决手头的问题。
CREATE TABLE records (id numeric, name text);
ALTER TABLE records ADD CONSTRAINT uniq UNIQUE (id) DEFERRABLE INITIALLY IMMEDIATE;
INSERT INTO records VALUES -- ^
(1, 'First record'), -- HERE
(3, 'Second record'),
(2, 'Third record'),
(4, 'Fourth record');