使用SqlAlchemy和ID为PostgreSQL创建测试数据

1 投票
2 回答
1287 浏览
提问于 2025-04-16 23:27

我正在尝试将一些示例数据放入我的数据库中,因此我创建了一个文件,这个文件可以构建我的模型,然后把这个模型的实例合并到数据库里。我使用合并的方式,是因为我希望能够重新运行这个文件,而不需要重新创建数据库或者清空所有的表。

不过,在查看我的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。

撰写回答