Python 将SQLAlchemy设置为使用PostgreSQL序列生成标识
背景: 我目前正在开发的应用程序正在从SQLite3过渡到PostgreSQL。使用当前数据库中的Python 将SQLAlchemy设置为使用PostgreSQL序列生成标识,python,sql,postgresql,sqlite,sqlalchemy,Python,Sql,Postgresql,Sqlite,Sqlalchemy,背景: 我目前正在开发的应用程序正在从SQLite3过渡到PostgreSQL。使用当前数据库中的.dump成功迁移了所有数据,更改了该类型的所有表 CREATE TABLE foo ( id INTEGER NOT NULL, bar INTEGER, ... PRIMARY KEY (id), FOREIGN KEY(bar) REFERENCES foobar (id), ... ); 到 和设置所有延迟的约束 因为我正在使用SQLAlc
.dump
成功迁移了所有数据,更改了该类型的所有表
CREATE TABLE foo (
id INTEGER NOT NULL,
bar INTEGER,
...
PRIMARY KEY (id),
FOREIGN KEY(bar) REFERENCES foobar (id),
...
);
到
和设置所有延迟的约束代码>
因为我正在使用SQLAlchemy,所以我希望从那时起,在更改引擎之后,事情会顺利进行。但问题似乎在于主键在INSERT
上自动递增到唯一值
表,比如说foo
,我目前有7500多行,但是序列foo\u id\u seq
的当前值设置为5
(因为我已经尝试了五次插入,现在都失败了)
问题:
因此,现在我的问题是,在INSERT
语句中,如果没有明确提供id
,如何使Postgres在foo
时自动为id
字段分配唯一值?或者更具体地说,序列是否为其返回唯一值
糖:
通过SQLAlchemy接口实现所有这些
环境详细信息:
- Python 2.6
- SQLAlchemy 8.2
- PostgreSQL 9.2
- psycopg2-2.5.1(dt十二月pq3扩展)
PS:如果有人发现这个问题的标题更合适,请编辑它。使用
alter sequence foo_id_seq restart with 7600
下次调用序列时,应该给您7601
然后是后续值。只需确保使用值>最后一个id重新启动它。您的主键
应定义为使用序列
作为默认值
,或者通过序列
伪类型:
CREATE TABLE blah (
id serial primary key,
...
);
或显式的序列
:
CREATE SEQUENCE blah_id_seq;
CREATE TABLE blah (
id integer primary key default nextval('blah_id_seq'),
...
);
ALTER SEQUENCE blah_id_seq OWNED BY blah.id;
这是
您可以将其添加到现有表中:
CREATE SEQUENCE blah_id_seq OWNED BY blah.id;
ALTER TABLE blah ALTER COLUMN id SET DEFAULT nextval('blah_id_seq');
如果希望恢复转储,请手动添加序列
如果使用COPY
或类似工具将现有数据直接加载到表中,则需要设置序列起点:
SELECT setval('blah_id_seq', max(id)+1) FROM blah;
我认为问题可能与您在SQLite中开发有关,然后执行转储并将该转储恢复到PostgreSQL。SQLAlchemy希望使用适当的默认值和序列自行创建模式
我建议您改为使用SQLAlchemy来创建一个新的空数据库。将每个表的数据从SQLite DB转储到CSV,然后将该数据复制到PostgreSQL表中。最后,使用setval
更新序列,以便生成适当的值
无论如何,您需要确保创建了适当的序列。您可以通过SERIAL
伪列类型,或通过手动SEQUENCE
创建和DEFAULT
设置来执行,但必须执行此操作。否则,无法以高效、并发安全的方式将生成的ID分配给表。对我来说似乎是一个临时解决方案。因为下一次使用显式提供的id
(=序列的当前值+1)值执行INSERT
,序列将为下一次INSERT
提供一个非唯一的值。啊,所以您插入的是显式id值。然后我会说“串行”没有意义,您的id应该只是一个普通整数。其次,我总共有25个序列,所以设置它们中的每一个看起来都很痛苦,实际上显式id
值是在迁移过程中提供的。除此之外,将来可能会出现这样一种情况,即显式提供一个id
,因此我不希望应用程序因为某些情况而出现错误。因此,请决定您要做什么。具有非锁定自动生成的ID或手动输入自己的值。从逻辑上讲,两者都不可能做到,不是吗?请始终在问题中给出您的PostgreSQL版本,以及其他适当的详细信息,如Python和psycopg2版本。包括您的版本有助于人们以后发现您的问题,有时还可以帮助我们更好地回答问题,因此,谢谢。在本例中,您没有运行任何古老或怪异的版本组合。相关设置引擎的回声我发现由SQLAlchemy生成的CREATE TABLE
语句与.dump
语句完全相同,除了SERIAL
子句<必须添加代码>可延迟
,以使设置的约束全部延迟代码>功能。所以我想这两种记录迁移方法的结果是一样的。@hus787编辑了答案,并添加了一条注释,指出了以后如何添加SEQUENCE
s,以防您需要这样做。这两种方法并不等价,正是因为SQLAlchemy正在生成一个SERIAL
伪列。您需要这样做,或者需要手动创建等效序列。
SELECT setval('blah_id_seq', max(id)+1) FROM blah;