我需要用uuid替换模型中的默认整数id。问题是它在另一个模型(外键)中使用了它。 有关如何在不丢失数据的情况下执行此操作的任何想法吗?
class A(Base):
__tablename__ = 'a'
b_id = Column(
GUID(), ForeignKey('b.id'), nullable=False,
server_default=text("uuid_generate_v4()")
)
class B(Base):
__tablename__ = 'b'
id = Column(
GUID(), primary_key=True,
server_default=text("uuid_generate_v4()")
)
不幸的是,它不起作用,我也担心我会打破这种关系。
sqlalchemy.exc.ProgrammingError: (psycopg2.ProgrammingError) default for column "id" cannot be cast automatically to type uuid
Alembic迁移我试过看起来类似于:
op.execute('ALTER TABLE a ALTER COLUMN b_id SET DATA TYPE UUID USING (uuid_generate_v4())')
答案 0 :(得分:2)
将id_tmp
列添加到b,其中包含自动生成的UUID值,并将b_id_tmp
列添加到a。更新外键上的连接b以使用相应的UUID填充a.b_id_tmp
。然后删除a.b_id
和b.id
,重命名添加的列,并重新建立主键和外键。
CREATE TABLE a(id int PRIMARY KEY, b_id int);
CREATE TABLE b(id int PRIMARY KEY);
ALTER TABLE a ADD CONSTRAINT a_b_id_fkey FOREIGN KEY(b_id) REFERENCES b(id);
INSERT INTO b VALUES (1), (2), (3);
INSERT INTO a VALUES (1, 1), (2, 2), (3, 2);
ALTER TABLE b ADD COLUMN id_tmp UUID NOT NULL DEFAULT uuid_generate_v1mc();
ALTER TABLE a ADD COLUMN b_id_tmp UUID;
UPDATE a SET b_id_tmp = b.id_tmp FROM b WHERE b.id = a.b_id;
ALTER TABLE a DROP COLUMN b_id;
ALTER TABLE a RENAME COLUMN b_id_tmp TO b_id;
ALTER TABLE b DROP COLUMN id;
ALTER TABLE b RENAME COLUMN id_tmp TO id;
ALTER TABLE b ADD PRIMARY KEY (id);
ALTER TABLE a ADD CONSTRAINT b_id_fkey FOREIGN KEY(b_id) REFERENCES b(id);
除此之外,索引v1 UUID比v4更有效,因为它们包含一些可重现的信息,如果你连续生成几个,你会注意到这些信息。除非出于外部安全原因需要更高的随机性,否则这是一笔不小的节省。