Ich mache eine Datenmigration zwischen zwei Tabellen (spaltet eine verwandte Tabelle aus). Die vorhandene Tabelle ist reminders
und hat eine start
-Spalte und eine neu hinzugefügte dateset_id
-Spalte, die auf eine neue dateset
-Tabelle verweist, die auch eine start
-Spalte enthält. Für jede Zeile in reminders
möchte ich INSERT
eine neue Zeile in dateset
mit dem Wert start
übernehmen und UPDATE
die entsprechende Zeile in reminders
mit der neu eingefügten dateset
ID .
Hier ist die SQL, die ich versucht habe:
%Vor% Ich erhalte den Fehler missing FROM-clause entry for table "reminder"
, weil ich die Spalte reminder.id
in die RETURNING
-Klausel einfüge, sie aber nicht für die Einfügung auswähle. Das macht Sinn, aber ich kann nicht herausfinden, wie ich die Abfrage modifizieren soll, um das zu tun, was ich brauche. Gibt es einen völlig anderen Ansatz, den ich vermisse?
Es gibt mehrere Möglichkeiten, das Problem zu lösen.
1. Fügen Sie vorübergehend eine Spalte hinzu
Wie bereits erwähnt, besteht der direkte Weg darin, vorübergehend eine Spalte reminder_id
zum dateset
hinzuzufügen. Füllen Sie es mit dem ursprünglichen IDs
aus reminder
table. Verwenden Sie es, um reminder
mit der Tabelle dateset
zu verbinden. Löschen Sie die temporäre Spalte.
2. Wenn start einzigartig ist
Wenn die Werte der Spalte start
eindeutig sind, ist es möglich, sie ohne zusätzliche Spalte auszuführen, indem Sie die Tabelle reminder
mit der Tabelle dateset
in der Spalte start
verbinden.
3. Wenn start nicht eindeutig ist
Es ist sogar in diesem Fall möglich, es ohne temporäre Spalte zu machen. Die Hauptidee ist folgendes. Sehen wir uns dieses Beispiel an:
Wir haben zwei Zeilen in reminder
mit dem gleichen start
-Wert und die IDs 3 und 7:
Nachdem wir sie in dateset
eingefügt haben, werden neue IDs generiert, zum Beispiel 1 und 2:
Es spielt keine Rolle, wie wir diese zwei Zeilen verknüpfen. Das Endergebnis könnte
sein %Vor%oder
%Vor%Beide Varianten sind korrekt. Das bringt uns zu folgender Lösung.
Fügen Sie einfach zuerst alle Zeilen ein.
%Vor% Übereinstimmen / verbinden Sie zwei Tabellen in start
Spalte mit dem Wissen, dass es nicht eindeutig ist. "Machen Sie es", indem Sie ROW_NUMBER
hinzufügen und durch zwei Spalten verbinden. Es ist möglich, die Abfrage kürzer zu machen, aber ich habe jeden Schritt explizit formuliert:
Ich hoffe, es ist klar aus dem Code, was es tut, vor allem, wenn Sie es mit der einfacheren Version ohne ROW_NUMBER
vergleichen. Offensichtlich funktioniert die komplexe Lösung auch dann, wenn start
eindeutig ist, aber sie ist nicht so effizient wie eine einfache Lösung.
Diese Lösung setzt voraus, dass dateset
vor diesem Prozess leer ist.
Hier ist eine andere Art, es zu tun, die sich von den drei Wegen unterscheidet, die Vladimir vorgeschlagen hat.
Mit einer temporären Funktion können Sie die ID der neu erstellten Zeilen sowie andere Werte in der Abfrage lesen:
%Vor% Diese Herangehensweise an das Problem ergab sich, nachdem ich festgestellt hatte, dass das Schreiben von INSERT ... RETURNING
als Unterabfrage das Problem lösen würde; Obwohl INSERT
s als Unterabfragen nicht erlaubt sind, sind Aufrufe von Funktionen sicherlich.
Interessanterweise deutet dies darauf hin, dass DML-Unterabfragen, die Werte zurückgeben, sehr nützlich sein können. Wenn sie möglich wären, würden wir einfach schreiben:
%Vor%Sie können Spalten nur mit RETURNING vom INSERT-Teil und nicht von der ausgewählten Tabelle zurückgeben. Also, wenn Sie bereit sind, eine Spalte reminder_id zu Ihrer Dateset-Tabelle hinzuzufügen,
%Vor%Die folgende Anweisung funktioniert:
%Vor%Nur wenn die Werte der Spalte start in Erinnerungen alle eindeutig sind , werden die folgenden beiden Anweisungen verwendet funktionieren auch:
%Vor%Das Problem besteht darin, dass Sie nur Spalten zurückgeben können, die in der Tabelle enthalten sind, in die Sie einfügen. Sie könnten es lösen, indem Sie dem Tabellen-Dataset eine zusätzliche Spalte geben, in die Sie reminder.id einfügen, damit Sie sie zurückgeben können.
Nach der Migration können Sie diese Spalte löschen.
Tags und Links sql postgresql