2016-05-15 5 views
0

Я пытаюсь объединить две таблицы с одинаковой структурой. В известном блоке строк первичный ключ (целое число auto_increment) используется в обеих таблицах для разных данных. Скажем, это строки с первичными ключами 2000-2150. Каков наилучший способ перенумеровать эти записи в таблице B на неиспользуемые значения (скажем, в диапазоне выше 3000), чтобы слияние продолжалось без конфликтов? Должен ли я просто ОБНОВИТЬ их на месте (например, добавив 1000 к каждому идентификатору в этом диапазоне), или есть ли лучшие способы?Слияние двух таблиц SQL с конфликтами ключей

Примечания:

  1. Все ссылки на эту таблицу объявляются ON UPDATE CASCADE, так что я могу спокойно пронумеровать их без последствий.

  2. Остальное слияние, с которым я могу справиться. Обе таблицы содержат полезные данные, и когда ключ за пределами этого диапазона повторяется, я буду держать версию в таблице А.

+0

Если бы вы могли, просьба предоставить запрос, который вы сейчас пытаетесь, чтобы у нас было что-то, что можно было бы отключить. Однако в качестве короткого ответа в вашем выборе «Таблица B» вы можете: «выбрать Id + 3000, col2, col3, col4 из TableB'. - То есть, если столбец 'Id' является числовым. – gmiley

+0

У меня пока нет запроса - я не уверен, какой подход взять. Я подумал о том, чтобы «UPDATE» добавить 1000 к каждому идентификатору в блоке, но я подумал, что спрошу, есть ли более подходящий подход. – alexis

+0

Хорошо, я просто переведу свой комментарий к ответу и, возможно, добавлю еще несколько мыслей. – gmiley

ответ

0

Изменение числа к отрицательному числа будет работать. Не было бы шансов на столкновение сейчас или в будущем.

+0

Спасибо, Я могу думать о многих сопоставлениях, которые разрешат столкновение (я бы предпочел добавить 1000). По-моему, мой вопрос: я просто «ОБНОВЛЯЮ» этот блок идентификаторов, или есть лучшие методы/подходы, доступные для такого типа вещь? – alexis

0

Перейдите от комментария к ответу.

Если бы вы могли, пожалуйста, предоставьте запрос, который вы сейчас пытаетесь, чтобы у нас было что-то, с чем можно было работать. Тем не менее, как короткий ответ ...

В вашем выборе таблица B вы можете:

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

То есть, если столбец Id числовой.

Следует отметить, что если вы попытаетесь вставить эти записи в Table A, вам необходимо отключить автоматическую последовательность.

Другой вариант, если вы собираетесь вставлять записи в Table A из Table B, откладывая возможные проблемы осиротевших детей записей из Table B, можно опустить Id столбец из Table B на SELECT INTO TableA..., когда вы делаете вставку, новое значение Id будет сгенерировано с идентификатором автоинкремента.

Для выдачи сиротских дочерних записей, вы также можете добавить новый столбец TableA под названием TableBId, который разместится оригинальный IdTableB из которых позволит вам получить доступ старых данных, связанных с TableB.Id. Другой альтернативой будет новая детская таблица для этой же идеи. Это помешает вам изменить структуру вашего TableA, но при этом по-прежнему обеспечит некоторый способ сохранения доступа к вашим старым данным.

Если бы у вас была больше информации о том, чего вы хотите в конечном счете, мы могли бы предложить гораздо лучшее решение, но это должно вас начать.

+0

Это звучит как хороший совет по всем, но ваш подход «на лету» не будет каскадировать изменение ID на связанные таблицы ... так что это не стартер. Таблица A больше не будет расти, поэтому ее можно модифицировать. – alexis

+0

Планируете ли вы, что это одно время? Вы удаляете одну из таблиц после выполнения слияния. или это будет продолжающийся сценарий типа репликации? Что касается изменений в дочерних записях, то это то, о чем я говорил, добавив новый столбец или, в идеале, добавить новую таблицу поиска, содержащую новый столбец Идентификатор, а также предыдущий столбец «Id» в отставке. – gmiley

0

Определить значение идентификаторов, которые "дублирующие"

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  

Сформировать новый "неиспользованный" идентификатор значение

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 дамп
  • отключить скрипты писать а и б
  • отключить AUTO_INCREMENT
  • caculate смещение (мин ID от б - макс ID от + 1)
  • записей починки в б (если каскадные работы)

    обновление б набор b.id = b.id + смещение где b.id в (выберите идентификатор из)

  • починки auto_increment обеих таблиц (устанавливается за последней записи)
  • позволяют auto_increment
  • включить скрипт, который записывает в таблицу сообщение об ошибке
  • производят в скрипт, который пытается писать в таблицу Ь, объясняя, что данные объединены с (или просто использовать таблицу там тоже)
  • переименования таблицы б в delete_after_2016_05_31_b

erm, что происходит с каскадными данными, которые все еще указывают на таблицу b?

это только «перемещает» дубликаты в новое место, также убедитесь, что никто не собирается восстанавливать удаленные данные из резервной копии в недвойственном диапазоне.

Другой подход - перейти к записи по записи и вставить данные в таблицу a, а затем использовать mysqllastinsertid для обновления всех записей, указывающих на старое значение.

Смежные вопросы