简体   繁体   English

通过SQLAlchemy在PostgreSQL中有两个串行键

[英]Having two serial keys in postgresql via sqlalchemy

I have an unusual challenge. 我面临着不寻常的挑战。 I'm modifying a table to be able to join with two other legacy groups of PostgreSQL tables. 我正在修改一个表,使其能够与其他两个旧的PostgreSQL表组连接。

One group pretty much requires that each record in the table have a unique integer. 一组几乎要求表中的每个记录都具有唯一的整数。 So, the following field definition would work: 因此,以下字段定义将起作用:

numeric_id = sql.Column(sql.Integer, primary_key=True) numeric_id = sql.Column(sql.Integer,primary_key = True)

The other group of tables all use UUID fields for the expected JOIN requests. 另一组表都将UUID字段用于预期的JOIN请求。 So the following field definition would work: 因此,以下字段定义将起作用:

uu_account_id = sql.Column(UUID(as_uuid=True), primary_key=True) uu_account_id = sql.Column(UUID(as_uuid = True),primary_key = True)

But, clearly, I can't have two primary keys. 但是,显然,我不能有两个主键。 So one of them needs to not be a primary key. 因此,其中之一不必是主键。 It would be nice to simply have both still be automatically assigned when a new record is made. 只需在创建新记录时同时自动将它们都分配即可。

Any suggestions? 有什么建议么?

I'm sure I can do a quick hack, but I'm curious if there is a nice clean answer. 我确定我可以快速进行破解,但是我很好奇是否有一个很好的答案。

(And no: changing the other tables is NOT an option. Way too much legacy code.) (并且不行:更改其他表是不行的。过多的遗留代码。)

Make the uuid column the primary key, like usual. 像往常一样,将uuid列设为主键。

Define the other column as having serial type and unique . 将另一列定义为具有serial类型和unique In SQL I'd write 在SQL中,我会写

create table mytable (
    mytable_id uuid primary key default uuid_generate_v4(),
    mytable_legacy_id serial unique not null,
    ... other cols ...
);

so you just need to do the SQLAlchemy equivalent, whatever that is, of a not null , unique field. 因此,您只需要对一个not null unique字段执行等效的SQLAlchemy。

Note that "serial" is just shorthand for 请注意,“ serial”仅是

create sequence tablename_colname_seq;
create table tablename (
    colname integer default nextval('tablename_colname_seq'),
    ... cols ...
);
alter sequence tablename_colname_seq owned by tablename.colname;

so if you can't make sqlalchemy recognise that you can have a serial field that isn't a primary key, you can do it this way instead. 因此,如果您无法使sqlalchemy识别出您可以拥有不是主键的串行字段,则可以改用这种方式。

Between the SQLAlchemy, alembic (which I also use), and PostgreSQL, this turned out to be tricky. 在SQLAlchemy,alembic(我也使用过)和PostgreSQL之间,事实证明这很棘手。

If creating a brand new table from scratch, the following works for my numeric_id column: 如果从头开始创建全新的表,则以下内容适用于我的numeric_id列:

numeric_id = sql.Column(sql.Integer, sql.Sequence('mytable_numeric_id_seq'), unique=True, nullable=False)

(It is possible that the unique=True and nullable=False are overkill.) unique=Truenullable=False会过大。)

However, if modifying an existing table, the sequence itself fails to get created. 但是,如果修改现有表,则序列本身无法创建。 Or, at least, I couldn't get it to work. 或者,至少,我无法使其正常工作。

The sequence can be created by hand, of course. 当然,可以手动创建序列。 Or, if using 'alembic' to make distributed migrations easier, add: 或者,如果使用“ alembic”使分布式迁移更容易,请添加:

from sqlalchemy.schema import Sequence, CreateSequence

def upgrade():
    op.execute(CreateSequence(Sequence("mytable_numeric_id_seq")))

To the version script created by alembic. 到由alembic创建的version脚本。

Special thanks to Craig for his help. 特别感谢Craig的帮助。

(Note: most of the SQLAlchemy examples on the net use db. as the module alias rather than sql. . Same thing really. I used sql. simply because I'm using db. already for MongoDB.) (注意:网上的大多数SQLAlchemy示例都使用db.作为模块别名而不是sql.确实是同一件事。我之所以使用sql.仅仅是因为我已经为MongoDB使用db. .。)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM