2017-03-08 1 views
0

Ich brauche die Standard-Integer-ID in meinem Modell mit einem UUID zu ersetzen. Das Problem ist, dass es in einem anderen Modell (Fremdschlüssel) verwendet wird. Haben Sie eine Idee, wie Sie diese Operation ausführen können, ohne Daten zu verlieren?mit UUID

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()") 
    ) 

Leider funktioniert es nicht, auch ich fürchte, ich werde die Beziehung brechen.

sqlalchemy.exc.ProgrammingError: (psycopg2.ProgrammingError) default for column "id" cannot be cast automatically to type uuid 

Alembic Migration Ich habe versucht, sieht ähnlich aus wie:

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

Antwort

2

eine id_tmp Spalte hinzufügen mit automatisch generierten UUID-Werte b, und eine b_id_tmp Spalte ein. Aktualisieren Sie einen Beitritt b auf dem Fremdschlüssel, um a.b_id_tmp mit den entsprechenden UUIDs zu füllen. Dann fallen a.b_id und b.id, benennen Sie die zusätzlichen Spalten und wiederherzustellen den Primärschlüssel und Fremdschlüssel.

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); 

Wie Nebenbei bemerkt, ist es effizienter zu indizieren v1 UUIDs als v4, da sie eine reproduzierbaren Informationen enthalten, die Sie feststellen, wenn Sie in einer Reihe mehr erzeugen. Das ist eine kleine Ersparnis, es sei denn, Sie benötigen die höhere Zufälligkeit für externe Sicherheitsgründe.

+0

Ich bin mir nicht sicher, ob ich bekommen, wie dies die bestehenden Beziehungen halten wird. Können Sie es über SQL-Syntax oder Python/Alembic-Code zeigen? – user2091046

+1

Es ist das SQL-Äquivalent des Sack-Sand-Tricks von Jäger der verlorenen Arche, wenn du das gesehen hast, außer mit weniger riesigen Felsbrocken. Ich habe ein Beispiel hinzugefügt. – dmfay