2017-03-08 158 views
0

我需要用uuid替換模型中的默認整數ID。問題在於它在另一個模型(foreignkey)中使用。 有關如何在不丟失數據的情況下執行此操作的任何想法?用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 

蒸餾器遷移我已經試過類似如下:

op.execute('ALTER TABLE a ALTER COLUMN b_id SET DATA TYPE UUID USING (uuid_generate_v4())') 

回答

2

添加id_tmp列與自動生成的UUID值B和b_id_tmp列到。使用相應的UUID更新外鍵上的加入b以填充a.b_id_tmp。然後刪除a.b_idb.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); 

正如順便說一句,這是更有效的指標比V4 V1的UUID,因爲它們包含一些可重複的信息,如果生成連續數,你會發現。除非您因外部安全原因需要更高的隨機性,否則這只是小幅節省。

+0

我不知道我得到這將如何保持現有的關係。 你可以通過SQL語法或python/alembic代碼顯示它嗎? – user2091046

+1

如果你已經看到了這個,那麼你就可以從「失落方舟攻略」中得到的沙袋技巧的SQL等價物,除非有更少的巨石。我已經添加了一個例子。 – dmfay