2016-05-15 168 views
0

我想合併(聯合)具有相同結構的兩個表。在已知的行塊中,主鍵(一個auto_increment整數)在兩個表中都用於不同的數據。假設這是主鍵2000-2150的行。將表B中的這些記錄重新編號爲未使用的值(例如,在3000以上的範圍內)的最佳方式是什麼,以便合併可以在沒有衝突的情況下繼續進行?我應該只是更新它們(比如,在該範圍內爲每個ID添加1000),還是有更好的方法?合併兩個SQL表與鍵衝突

注:

  1. 此表的所有文獻都宣告ON UPDATE CASCADE,這樣我就可以放心地重新編號他們沒有後果。

  2. 我可以處理的其餘合併。這兩個表包含有用的數據,而當重複該範圍之外的關鍵,我會繼續版本表A

+0

如果可以,請提供您現在正在嘗試的查詢,以便我們有一些工作要做。然而作爲一個簡短的回答,在你選擇的'表B'中,你可以:'從表B選擇Id + 3000,col2,col3,col4。 - 也就是說,如果「Id」列是數字。 – gmiley

+0

我還沒有查詢 - 我不確定採取哪種方法。我想過做一個'UPDATE'來爲塊中的每個ID添加1000,但我想我會問是否有更合適的方法。 – alexis

+0

好吧,我只是將我的評論移到答案然後可能會增加幾個想法。 – gmiley

回答

0

的數字更改爲數字的負會工作。現在或將來不會有碰撞的機會。

+0

Thanks- - 我可以想到很多可以解決碰撞的映射(我寧願添加1000),我想我的問題是,我只是'更新'這個ID塊,還是有更好的方法/方法可用於這種類型的事情? – alexis

0

從評論移到答案。

如果可以,請提供您現在正在嘗試的查詢,以便我們有一些工作要做。但是作爲一個簡單的答案...

在您選擇表B你可以的:

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

也就是說,如果ID列數字。

有一點需要注意,如果您要嘗試將這些記錄插入Table A,則需要禁用自動排序。

另一種選擇,如果你要記錄從Table B插入Table A,從Table B留出的孤立子記錄可能出現的問題,你可以從Table BSELECT INTO TableA...省略Id列當你插入的,將使用自動增量ID生成新的Id值。

對於孤殘兒童的記錄問題,你還可以添加一個新列TableA稱爲TableBId會從TableB房子原來Id這將允許您仍然可以訪問相關聯TableB.Id舊數據。另一種選擇是爲這個想法創建一個新的子表。這樣可以防止您必須更改TableA結構,但仍然可以提供某種方法來保留對舊數據的訪問權限。

如果你有更多關於你最終想做什麼的信息,我們可能會想出更好的解決方案,但這應該讓你開始。

+0

這聽起來像是一個很好的建議,但你的實時方法不會將ID變更級聯到相關的表......所以這是一個非起動器。表A不會再增長,所以修改是安全的。 – alexis

+0

你打算這是一次性的東西嗎?執行合併後,您是否退出其中一個表格?或者這會是一個持續的複製類型場景?至於對子記錄的更改,我正在通過添加一個新列或者理想情況下添加一個包含新Id列以及之前已退役的表「Id」列的新查找表。 – gmiley

0

識別ID值被 「複製」

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

尋找新的 「身份證」 的價值觀

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  

生成新的 「未使用」 的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 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

,如果你更經常這樣做,嘗試其他類似一些花哨的方式描述,如果是把事情做好一個計時器,只是做了簡單的方法,並確保你不要破壞任何東西:

  • 創建MySQL轉儲
  • 禁用腳本寫a和b
  • 禁用AUTO_INCREMENT
  • caculate偏移(分鐘ID從b - 從一個+ 1最大ID)
  • 修復條目b(如果在層疊作品)

    更新B設置b.id = b.id + offset其中在(選擇從ID)這兩個表的

  • 修復AUTO_INCREMENT b.id(設置最後一個條目的後面)
  • 使AUTO_INCREMENT
  • 使腳本在嘗試寫入表b腳本寫入表
  • 產生錯誤消息,說明數據已經用合併(或只使用表中的有太多)
  • 重命名錶b鍵delete_after_2016_05_31_b

erm,級聯數據仍然指向表b的情況如何?

這隻能「移動」重複到一個新的位置,還要確保沒有人會從非重複範圍的備份中恢復已刪除的數據。

另一種方法是按記錄進行記錄並將數據插入到表a中,然後使用mysqllastinsertid更新指向舊值的所有條目。