将SQLAlchemy设置为使用PostgreSQL SERIAL进行标识生成

时间:2013-07-17 11:23:56

标签: 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),
    ...
);

CREATE TABLE foo (
    id SERIAL NOT NULL, 
    bar INTEGER,
    ...
    PRIMARY KEY (id),
    FOREIGN KEY(bar) REFERENCES foobar (id) DEFERRABLE,
    ...
);

SET CONSTRAINTS ALL DEFERRED;

因为我正在使用SQLAlchemy,所以我希望从那时开始顺利工作,当然要改变engine。但问题似乎是主键自动增加到INSERT上的唯一值。

该表格,foo,我目前遇到问题,有7500多行,但序列foo_id_seq的{​​{1}}设置在current value上(因为我有尝试插入五次,现在所有插件都失败了。)

问题:

所以现在我的问题是,如果没有明确提供5,在id语句中,如果{{1,我如何让Postgres自动为INSERT字段分配唯一值}}?或者更具体地说,让序列为它返回一个唯一值?

糖:

通过SQLAlchemy界面实现所有这些。

环境详情:

  • Python 2.6
  • SQLAlchemy 8.2
  • PostgreSQL 9.2
  • psycopg2 - 2.5.1(dt dec pq3 ext)

PS:如果有人为此问题找到更合适的标题,请进行编辑。

2 个答案:

答案 0 :(得分:1)

您的PRIMARY KEY应该被定义为使用SEQUENCE作为DEFAULT,通过SERIAL便利伪类型:

CREATE TABLE blah (
    id serial primary key,
    ...
);

或明确的SEQUENCE

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;

这是discussed in the SQLAlchemy documentation

您可以将其添加到现有表格中:

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,然后将COPY该数据转储到PostgreSQL表中。最后,使用setval更新序列,以便生成适当的值。

无论如何,需要以确保创建适当的序列。您可以通过SERIAL伪列类型或手动SEQUENCE创建和DEFAULT设置来执行此操作,但您必须这样做。否则,无法以高效,并发安全的方式将生成的ID分配给表。

答案 1 :(得分:0)

使用

alter sequence foo_id_seq restart with 7600
下次调用序列时,

应该给你7601。

http://www.postgresql.org/docs/current/static/sql-altersequence.html

然后是后续的价值观。只需确保使用值>重新启动它最后的身份。