Xiè*_*léi 10 postgresql identity auto-increment compact-database
运行了很长时间后,我在id字段中得到越来越多的漏洞.一些表的id是int32,id序列达到了它的最大值.一些Java源代码是只读的,因此我不能简单地将id列类型更改为int32to long,这会破坏API.
我想重新编号.这可能不是一个好的做法,但好或坏并不关心这个问题.我想重新编号,特别是那些很长的ID,如"61789238","548273826529524324".我不知道它们为什么这么长,但更短的ID也更容易手动处理.
但由于引用和约束,手动压缩ID并不容易.
PostgreSQL本身是否支持ID重新编号?或者是否有任何插件或维护工具?
也许我可以写一些存储过程?那将是非常好的,所以我可以每年安排一次.
unp*_*nic 13
假设您的id是从bignum序列生成的,只是RESTART序列并用表更新表idcolumn = DEFAULT.
CAVEAT:如果此id列被其他表用作外键,请确保已打开on update cascade修改器.
例如:
创建表,放入一些数据,并删除中间值:
db=# create sequence xseq;
CREATE SEQUENCE
db=# create table foo ( id bigint default nextval('xseq') not null, data text );
CREATE TABLE
db=# insert into foo (data) values ('hello'), ('world'), ('how'), ('are'), ('you');
INSERT 0 5
db=# delete from foo where data = 'how';
DELETE 1
db=# select * from foo;
id | data
----+-------
1 | hello
2 | world
4 | are
5 | you
(4 rows)
Run Code Online (Sandbox Code Playgroud)
重置您的序列:
db=# ALTER SEQUENCE xseq RESTART;
ALTER SEQUENCE
Run Code Online (Sandbox Code Playgroud)
更新您的数据:
db=# update foo set id = DEFAULT;
UPDATE 4
db=# select * from foo;
id | data
----+-------
1 | hello
2 | world
3 | are
4 | you
(4 rows)
Run Code Online (Sandbox Code Playgroud)
Erw*_*ter 11
这个问题已经过时了,但是在尝试应用此处建议的内容之后,我们从dba.SE上的绝望用户那里得到了一个新问题.在那里找到更多细节和解释的答案:
在大多数情况下,目前接受的答案 将失败.
通常,您对列有一个PRIMARY KEY或UNIQUE约束,默认情况下.(OP提及.)在每行之后检查这样的约束,因此您很可能会尝试唯一的违规错误.细节:idNOT DEFERRABLEreferences and constraints
通常,人们希望在缩小差距时保留行的原始顺序.但是更新行的顺序是任意的,导致任意数字.所演示的示例似乎保留了原始序列,因为物理存储仍然与所需的顺序一致(在前一刻按所需顺序插入行),这在现实世界的应用程序中几乎不是这种情况,并且完全不可靠.
事情比起初看起来更复杂.一个解决方案(以及其他解决方案),如果您可以暂时删除PK/UNIQUE约束(和相关的FK约束):
BEGIN;
LOCK tbl;
-- remove all FK constraints to the column
ALTER TABLE tbl DROP CONSTRAINT tbl_pkey; -- remove PK
-- for the simple case without FK references - or see below:
UPDATE tbl t -- intermediate unique violations are ignored now
SET id = t1.new_id
FROM (SELECT id, row_number() OVER (ORDER BY id) AS new_id FROM tbl) t1
WHERE t.id = t1.id;
-- Update referencing value in FK columns at the same time (if any)
SELECT setval('tbl_id_seq', max(id)) FROM tbl; -- reset sequence
ALTER TABLE tbl ADD CONSTRAINT tbl_pkey PRIMARY KEY(id); -- add PK back
-- add all FK constraints to the column back
COMMIT;
Run Code Online (Sandbox Code Playgroud)
这也是很多的大表更快,因为检查PK(和FK)约束(S)的每一行的成本比拆卸约束(S)和增加它(它们)背多了不少.
如果其他表中有FK列引用tbl.id,请使用数据修改CTE来更新所有这些列.
表fk_tbl和FK列的示例fk_id:
WITH u1 AS (
UPDATE tbl t
SET id = t1.new_id
FROM (SELECT id, row_number() OVER (ORDER BY id) AS new_id FROM tbl) t1
WHERE t.id = t1.id
RETURNING t.id, t1.new_id -- return old and new ID
)
UPDATE fk_tbl f
SET fk_id = u1.new_id -- set to new ID
FROM u1
WHERE f.fk_id = u1.id; -- match on old ID
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
4178 次 |
| 最近记录: |