更新数字列,以便其字段的值构建以x开头的序列

问题描述 投票:1回答:2

给出这样的表:

+----+-----
| id | ...
+----+-----
|  4 | foo
|  2 | bar
|  7 | baz
|  5 | gux
|  . | ...
|  . | ...
|  . | ...
|    |

我想为其中的所有记录分配新的ID,以便它们构建序列

an = an-1 + 1; a0 = x我在哪里定义x

所以例如随着x设为8,桌子就会变成

+----+-----
| id | ...
+----+-----
|  8 | foo
|  9 | bar
| 10 | baz
| 11 | qux
|  . | ...
|  . | ...
|  . | ...
|    |

UPDATE语句如何?

sql postgresql
2个回答
1
投票
  1. 有可变的id是一个非常糟糕的设计。
  2. 如果x <max(id),您将遇到重复ID的问题,并且事务将失败。

但是,如果您正在为测试或非常具体的任务执行此操作,并且您知道可能存在的问题,则可以使用以下序列执行此操作:

例如:x = 2000

    CREATE SEQUENCE myseq START 2000;
    update mytable set id = nextval('myseq');

显然你会失去原来的id命令。


1
投票

我可以看到这对于其他用例非常难以预测,我同意@mnesarco的设计评论。总而言之,这是一个解决方案,可能会执行您在问题中描述的内容:

with baz as (
  select
    id, bar,
    row_number() over (order by 1) as rn,
    max (id) over (partition by 1) as max_id
  from
    foo
)
update foo
set
  id = baz.max_id + baz.rn
from baz
where
  foo.id = baz.id

我有一个真正的警告是,这就是说“按行排序行”(解析函数中的order by 1),这是一件非常奇怪的事情。由于PostgreSQL使用MVCC进行DML的方式,单个更新将使该行“结束”到表的末尾。订单永远不是隐含的,因此除非您明确告诉它为什么这些ID按顺序排列,否则无法保证这将按您希望的方式分配ID。如果有一些我们可以隐式排序的列或列,我会感觉好多了 - 那么我会对你的问题采用这种方法感觉很好。

© www.soinside.com 2019 - 2024. All rights reserved.