Python 将SQLAlchemy设置为使用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

背景:

我目前正在开发的应用程序正在从SQLite3过渡到PostgreSQL。使用当前数据库中的
.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;