4

背景:

我目前正在开发的应用程序正在从 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_seqcurrent value因为5我已经尝试了五次插入,但都失败了)。

问题:

所以现在我的问题是,如果没有idINSERT语句中明确提供 , 我怎样才能让 Postgres 自动为该id字段分配一个唯一值 if foo?或者更具体地说,序列是否为它返回一个唯一值?

糖:

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

环境细节:

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

PS:如果有人为这个问题找到更合适的标题,请编辑它。

4

2 回答 2

1

PRIMARY KEY应该被定义为使用 aSEQUENCE作为 a 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;

在 SQLAlchemy 文档中进行了讨论

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

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 分配给表。

于 2013-07-18T01:44:16.507 回答
0

利用

alter sequence foo_id_seq restart with 7600

下次调用序列时应该给你 7601。

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

然后是后续值。只需确保使用值 > 最后一个 id 重新启动它。

于 2013-07-17T11:28:37.130 回答