使用SqlAlchemy和ID为PostgreSQL创建测试数据
我正在尝试将一些示例数据放入我的数据库中,因此我创建了一个文件,这个文件可以构建我的模型,然后把这个模型的实例合并到数据库里。我使用合并的方式,是因为我希望能够重新运行这个文件,而不需要重新创建数据库或者清空所有的表。
不过,在查看我的Postgres表的主键序列时,我发现我的my_items_id_seq在插入了10个项目后显示了以下内容:
Sequence "public.my_items_id_seq"
Column | Type | Value
---------------+---------+---------------------
sequence_name | name | my_items_id_seq
last_value | bigint | 1
start_value | bigint | 1
increment_by | bigint | 1
max_value | bigint | 9223372036854775807
min_value | bigint | 1
cache_value | bigint | 1
log_cnt | bigint | 0
is_cycled | boolean | f
is_called | boolean | t
我该如何在合并数据时增加last_value呢?
[编辑]
这里的主要问题是,在插入数据后,我无法再往数据库中添加项目,因为会出现SqlAlchemy的完整性错误。这是因为PostgreSQL试图用id为1的新实例进行插入。
2 个回答
0
我也遇到过同样的问题,不过我是在尝试为不同的模型插入数据。
下面这段小代码来自PostgreSQL的维基,它正好可以满足你的需求,而且适用于你数据库中的每一个序列。
SELECT 'SELECT SETVAL(' ||
quote_literal(quote_ident(PGT.schemaname) || '.' || quote_ident(S.relname)) ||
', COALESCE(MAX(' ||quote_ident(C.attname)|| '), 1) ) FROM ' ||
quote_ident(PGT.schemaname)|| '.'||quote_ident(T.relname)|| ';'
FROM pg_class AS S,
pg_depend AS D,
pg_class AS T,
pg_attribute AS C,
pg_tables AS PGT
WHERE S.relkind = 'S'
AND S.oid = D.objid
AND D.refobjid = T.oid
AND D.refobjid = C.attrelid
AND D.refobjsubid = C.attnum
AND T.relname = PGT.tablename
ORDER BY S.relname;
这段代码看起来有点神奇,但实际上它做的事情和被接受的答案所建议的完全一致。
2
这个回答的第一部分是通过阅读一个关于Django和PostgreSQL的链接得来的,作者在里面也尝试用索引来填充迁移数据。
他的解决办法是先找到最大的索引,然后执行以下查询:
alter sequence profile_billingaddress_id_seq restart with {id};
通过这个,我发现了PostgreSQL文档中关于序列操作函数的正确关键词。推荐的做法是执行这个查询:
select setval('my_items_id_seq', {id})
... 这里的{id}显然是一个真实整数的占位符。我还注意到,last_value其实就是next_value的最后一个返回值。这一点很重要,因为使用setval而不是上面提到的alter sequence可以确保nextval返回一个未使用的索引。也就是说,当使用setval时,如果id=10,nextval会返回11。而如果使用alter sequence命令,当id=10时,nextval也会返回10。