2017-10-09 60 views
2

现有记录我与它记录的现有表,我只是增加了一个新的列ver,我想是唯一的。更新与唯一的整数

create table foo (
    bar text, 
    ver integer 
); 

select * from foo; 

bar ver 
--- --- 
one null 
two null 
three null 

我正在努力如何做到这一点出于某种原因。

我想要做的事,如:

update foo set ver = (select generate_series(1, 1000)); 

也许

update foo set ver = v from (select generate_series(1, 1000) as v); 

...但当然这些都不工作。任何人都可以指出我的明显吗?

+1

如果您希望成为未来行唯一为好,然后用序列 –

+0

@a_horse_with_no_name - 不,我不需要(或希望)说。我只需要确保现有记录变得独特。 (在我的实际代码中,我正在编写一个可应用于生产数据库的SQL迁移:添加列,填充列,添加唯一索引。) –

回答

4

你需要一个主键(或唯一列)单独更新的行表。在缺少这样的列,你可以使用隐藏列ctid其定义是唯一的,例如:

update foo f 
set ver = rn 
from (
    select ctid, row_number() over (order by ctid) as rn 
    from foo 
    ) s 
where f.ctid = s.ctid 
+0

嗯,这当然有效,但我认为这会带我有一段时间了解为什么......实际上,我的真正表格确实有一个唯一的ID,而我目前用'update foo set ver = id;'解决了这个问题 - 但我无法相信这是唯一的或最好的解! –

+0

您可以使用'id'而不是'ctid'。该解决方案给出从1开始的相连数字。当然,如果满足您的所有要求,简单分配'id'是最好的选择。 – klin

+0

请勾选。这是最好的答案,它非常聪明。 (它是否担心别人,我们不得不求助于这个聪明程度,但?) –

1

使用一些PL/pgSQL的代码:

DO 
$$DECLARE 
    c CURSOR FOR SELECT * FROM foo; 
    x foo; 
    i integer := 1; 
BEGIN 
    OPEN c; 
    LOOP 
     FETCH c INTO x; 
     EXIT WHEN NOT FOUND; 
     UPDATE foo SET ver = i WHERE CURRENT OF c; 
     i := i + 1; 
    END LOOP; 
END;$$; 

然后你就可以添加一个唯一约束:

ALTER TABLE foo ADD UNIQUE(ver); 
0

首先,创建一个序列。

create sequence foo_ver; 

然后添加具有序列中下一个数字的默认值的列。

alter table foo add ver integer default nextval('foo_ver') not null; 

数据自动填充,新记录会自动获得一个新的唯一编号。

可选:创建唯一索引以确保万无一失。

create unique index on foo(ver); 
+0

我已经说过,我特别不想这样做。展望未来,这个专栏不会是一个简单的序列。它将由应用程序填充。我只需要一种方法来填充现有记录 - 正如我在问题的评论中所说的那样。 –

+0

问:为什么你不需要新记录也是唯一的? –

+0

欲了解更多信息,请重新阅读我的原创评论给您的答案。 ;) –