Удаление повторяющихся строк с первичными ключами, которые связаны с другими таблицами - PullRequest
0 голосов
/ 02 августа 2020

Процесс создавал повторяющиеся строки в таблице, где их не должно было быть. Есть несколько отличных ответов на удаление повторяющихся строк в Интернете. Но что, если эти дубликаты с первичными ключами ID имеют привязанные к ним данные в других таблицах?

Есть ли способ удалить все дубликаты в первой таблице и перенести все данные, связанные с этими ключами, в один ПК Идентификатор, который не был удален?

Например:

TABLE 1
+-------+----------+----------+------------+
| ID(PK)| Model    | ItemType | Color      |
+-------+----------+----------+------------+
| 1     | 4        | B        | Red        |
| 2     | 4        | B        | Red        |
| 3     | 5        | A        | Blue       |
+-------+----------+----------+------------+

TABLE 2
+-------+----------+---------+
| ID(PK)| OtherID  | Type    |
+-------+----------+---------+
| 1     | 1        | Type1   |
| 2     | 1        | Type2   |
| 3     | 2        | Type3   |
| 4     | 2        | Type4   |
| 5     | 2        | Type5   |
+-------+----------+---------+

Итак, теоретически я бы хотел удалить запись с ID: 2 из ТАБЛИЦА 1 , а затем переключите поля OtherID в ТАБЛИЦА 2 на 1 . Это действительно необходимо для X таблиц. В этой конкретной ситуации к его идентификатору PK подключены 4 таблицы.

Ответы [ 2 ]

1 голос
/ 02 августа 2020

Вы не можете сделать это автоматически. Но вы можете сделать это с помощью некоторых запросов. Сначала вы устанавливаете для всех внешних ключей правильный идентификатор, который предположительно является наименьшим:

with ids (
      select t1.*, min(id) over (partition by Model, ItemType, Color) as min_id
      from table1 t1
     )
update t2
    set t2.otherid = ids.min_id
    from table2 t2 join
         ids
         on t2.otherid = ids.id
    where ids.id <> ids.min_id; 

Затем удаляете идентификаторы, которые либо дублируются, либо не упоминаются в table2 (в зависимости от того, какой вы на самом деле хотите):

with ids (
      select t1.*, min(id) over (partition by Model, ItemType, Color) as min_id
      from table1 t1
     )
delete from ids
    where id <> min_id;

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

1 голос
/ 02 августа 2020

Чтобы сделать это правильно, вы хотите обернуть все в одну транзакцию и выполнять это в течение обычного периода обслуживания. Все остальное может привести к тому, что вещи будут такими же непоследовательными, как сейчас.

  1. Определите, какой «ключ» вы будете использовать.
  2. Обновите все дочерние таблицы, чтобы использовать новый «ключ», где значением является старый «ключ».
  3. Не должно быть зависимостей FK от повторяющихся записей, удалите их.
  4. После того, как все неоднозначности разрешены, наложите уникальное ограничение на (ItemType,Color) (или любые другие реальные столбцы).

Если имеется много экземпляров, вам может потребоваться написать сценарий для обработки этого и использовать информацию в sys.foreign_keys и sys.foreign_key_columns, чтобы определить, какие записи обновлять и в каком порядке.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...