2016-05-15 1 views
0

Ich versuche, zwei Tabellen mit der gleichen Struktur (Vereinigung) zusammenzuführen. In einem bekannten Zeilenblock wird der Primärschlüssel (eine ganze Zahl auto_increment) in beiden Tabellen für unterschiedliche Daten verwendet. Nehmen wir an, es sind die Zeilen mit den Primärschlüsseln 2000-2150. Was ist der beste Weg, um diese Datensätze in Tabelle B zu unbenutzten Werten neu zu nummerieren (sagen wir im Bereich über 3000), damit die Zusammenführung ohne Konflikte ablaufen kann? Sollte ich sie nur aktualisieren (sagen wir, indem man jeder ID in diesem Bereich 1000 hinzufügt), oder gibt es bessere Möglichkeiten?Zwei SQL-Tabellen mit Schlüsselkonflikten verschmelzen

Hinweise:

  1. Alle Verweise auf diese Tabelle sind ON UPDATE CASCADE erklärt, so dass ich sicher ohne Konsequenzen nummerieren kann.

  2. Der Rest der Zusammenführung kann ich behandeln. Beiden Tabellen enthalten nützliche Daten, und wenn eine Taste außerhalb dieses Bereichs wiederholt wird, werde ich die Version in Tabelle A hält

+0

Wenn Sie könnten, geben Sie bitte die Abfrage, die Sie jetzt versuchen, so dass wir etwas haben, von dem wir arbeiten können. Als kurze Antwort können Sie jedoch in der Auswahl von 'Tabelle B':' Id + 3000, col2, col3, col4 von TableB' auswählen. - Das heißt, wenn die Spalte "Id" numerisch ist. – gmiley

+0

Ich habe noch keine Frage - Ich bin unsicher, welchen Ansatz ich wählen soll. Ich dachte daran, ein 'UPDATE' zu machen, um jeder ID im Block 1000 hinzuzufügen, aber ich dachte, ich würde fragen, ob es einen geeigneteren Ansatz gibt. – alexis

+0

Ok, ich werde meinen Kommentar dann auf eine Antwort verschieben und vielleicht ein paar weitere Gedanken hinzufügen. – gmiley

Antwort

0

die Zahlen zu den Negativen der Zahl ändern funktionieren würde. Eine Kollision würde jetzt oder in Zukunft nicht möglich sein.

+0

Danke - Ich kann mir viele Mappings vorstellen, die die Kollision auflösen (ich würde lieber 1000 hinzufügen.) Ich denke, meine Frage ist, ob ich diesen Block von IDs nur 'UPDATE', oder gibt es bessere Methoden/Ansätze für diese Art von Ding? – alexis

0

Von Kommentar zu Antwort wechseln.

Wenn Sie könnten, bitte geben Sie die Abfrage, die Sie jetzt versuchen, so dass wir etwas zum Arbeiten haben von. Doch als kurze Antwort ...

In Ihrer select der Tabelle B konnte man:

select Id, col2, col3, col4 
from TableA 
union all 
select Id + 3000, col2, col3, col4 
from TableB; 

Das heißt, wenn die ID-Spalte numerisch ist.

Eine Sache zu beachten, wenn Sie dann versuchen werden, diese Datensätze in Table A einzufügen, müssen Sie die automatische Sequenzierung deaktivieren.

Eine weitere Option, wenn Sie die Datensätze in Table A von Table B einfügen werden, von Table B die möglichen Probleme der verwaisten Kind Aufzeichnungen beiseite, können Sie die Id Spalte von Table B auf einem SELECT INTO TableA... als wenn Sie das tun, den Einsatz verzichtet werden könnte, Ein neuer Id Wert wird mit der Auto-Inkrement-ID generiert.

Für die Ausgabe von verwaisten Kind Aufzeichnungen, man könnte auch eine neue Spalte TableATableBId genannt hinzufügen, die die ursprüngliche Id von TableB Haus würde, die Sie noch erlauben würde, die alten Daten zu TableB.Id zugeordnet zugreifen. Eine andere Alternative wäre eine neue Kindtabelle für dieselbe Idee. Dies würde verhindern, dass Sie Ihre TableA Struktur ändern müssen, und dennoch eine Möglichkeit bieten, den Zugriff auf Ihre alten Daten zu behalten.

Wenn Sie mehr Informationen darüber hätten, was Sie letztendlich tun möchten, könnten wir möglicherweise eine viel bessere Lösung finden, aber das sollte Ihnen den Einstieg erleichtern.

+0

Das hört sich nach einem guten Rat an, aber Ihr On-the-Fly-Ansatz wird die ID-Änderung nicht auf verwandte Tabellen kaskadieren ... also ist das kein Ansporn. Tabelle A wird nicht mehr wachsen, daher kann sie geändert werden. – alexis

+0

Planen Sie, dass dies eine einmalige Sache ist? Scheiden Sie eine der Tabellen aus, nachdem Sie die Zusammenführung durchgeführt haben. oder wird dies ein fortlaufendes Replikationsszenario sein? Was die Änderungen an untergeordneten Datensätzen angeht, habe ich darüber gesprochen, indem ich entweder eine neue Spalte hinzufügte oder idealerweise eine neue Nachschlagetabelle hinzufügte, die sowohl die neue Id-Spalte als auch die vorherige Spalte "Id" der zurückgezogenen Tabellen enthielt. – gmiley

0

die ID-Werte identifizieren, die

SELECT b.id 
    FROM b 
    JOIN a 
    ON b.id = a.id 

neue "id" Identify Werte "dupliziert" werden

SELECT MAX(m.id) 
    FROM (SELECT MAX(ma.id) AS id 
      FROM a ma 
      UNION ALL 
     SELECT MAX(mb.id) AS id 
      FROM b mb 
     ) m  

Neuen "nicht verwendete" id

SELECT s.id   AS old_id 
     , @id := @id + 1 AS new_id 
    FROM (SELECT b.id 
      FROM b 
      JOIN a 
       ON b.id = a.id 
      ORDER BY b.id 
     ) s 
CROSS 
    JOIN (SELECT @id := MAX(ma.id) FROM a ma) i 
ORDER 
    BY s.id 

Update durchführen Werte

UPDATE b t 
    JOIN (SELECT r.* 
      FROM (SELECT s.id   AS old_id 
         , @id := @id + 1 AS new_id 
        FROM (SELECT b.id 
           FROM b 
           JOIN a 
           ON b.id = a.id 
          ORDER BY b.id 
         ) s 
        CROSS 
        JOIN (SELECT @id = MAX(m.id) 
          FROM (SELECT MAX(ma.id) AS id 
             FROM a ma 
            UNION ALL 
            SELECT MAX(mb.id) AS id 
             FROM b mb 
           ) m  
         ) i 
        ORDER 
         BY s.id 
       ) r 
     ) q 
    ON t.id = q.old_id 
    SET t.id = q.new_id 
0

, wenn Sie es regelmäßig tun, versuchen einige phantastische Weise wie die anderen beschreiben, wenn es sich um eine Dinge zu erledigen ein Timer ist, es nur tun, um die einfache Art und Weise und stellen Sie sicher, dass Sie brechen nicht alles:

  • erstellen mysql
  • deaktivieren Skripte Dump a und b
  • disable auto_increment
  • caculate Offset (min id von b - max id von a + 1) Schreiben
  • fix Einträge in b (wenn Kaskade Werke)

    Update b Satz b.id = b.id + Offset, wo b.id in (select id aus a)

  • fix auto_increment beiden Tabellen (hinter dem letzten Eintrag gesetzt) ​​
  • ermöglichen auto_increment
  • ermöglichen Skript, das eine
  • produziert Fehlermeldung in Skript-Tabelle schreibt, die Tabelle b zu schreiben versucht, diese Daten zu erklären hat mit einem verschmolzen (oder nur dort verwenden Tabelle)
  • Umbenennungs Tabelle b delete_after_2016_05_31_b

Ähm, was passiert mit den kaskadierten Daten, die immer noch auf Tabelle b zeigen?

Dies "verschiebt" nur Duplikate an einen neuen Ort, stellen Sie auch sicher, dass niemand jemals gelöschte Daten von einem Backup im nicht-duplizierten Bereich wiederherstellen wird. Ein anderer Ansatz besteht darin, Datensatz für Datensatz aufzuzeichnen und die Daten in Tabelle a einzufügen und dann mysqllastinsertid zu verwenden, um alle Einträge zu aktualisieren, die auf den alten Wert zeigen.