I have an unusual challenge. I'm modifying a table to be able to join with two other legacy groups of PostgreSQL tables.
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)
The other group of tables all use UUID fields for the expected JOIN requests. So the following field definition would work:
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.
Define the other column as having serial
type and unique
. In SQL I'd write
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.
Note that "serial" is just shorthand for
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.
Between the SQLAlchemy, alembic (which I also use), and PostgreSQL, this turned out to be tricky.
If creating a brand new table from scratch, the following works for my numeric_id
column:
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.)
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:
from sqlalchemy.schema import Sequence, CreateSequence
def upgrade():
op.execute(CreateSequence(Sequence("mytable_numeric_id_seq")))
To the version
script created by alembic.
Special thanks to Craig for his help.
(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.)
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.