sql перенос данных из одной таблицы в другую

15 апреля 2016 г. 20:25

Возникла следующая проблема: для некоторого приложения нужно было удалить поле tags = TaggableManager(blank=True) (и соответственно зависимость django-taggit). Как обычно, стираю это поле и вызываю makemigration, который сделал своё дело как надо. Но при вызове migrate для другого проекта с тем же набором миграций происходит ошибка, что приложение taggit не найдено для выполнения миграций. Оно, конечно, и логично, что миграции будут требовать это приложение.

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

Перенос данных из таблицы разной структуры

Допустим, у нас есть приложение projects и таблица projects_project с полями:

  1. id
  2. link (ссылка на страницу проекта)
  3. title_in_link (показываемая подсказка при наведении на ссылку)
  4. order (путь до картинки)
  5. border_color (цвет границы)
  6. tags (теги)

Мы хотим следующую структуру:

  1. id
  2. link
  3. hint
  4. order
  5. is_border
  6. border_color
  7. border_width

Тем самым мы видим следующие изменения:

  1. title_in_link переименовался в hint.
  2. Добавилось поле is_boder, при этом оно обязательно для заполнения.
  3. border_width, которое может быть пустым.
  4. Удалилось поле tags

А теперь "вручную" исправим структуру таблицы:

  1. Переименовываем таблицу: projects_project -> projects_project_old.
  2. Удаляем все миграции приложения, а также удаляем соответствующие записи миграций в таблице django_migrations в базе данных.

Чтобы удалить миграции определённых приложений в базе данных, я обычно захожу в pgadmin, нажимаю просмотр данных таблицы django_migrations, ввожу условие фильтрации, например:

app = 'picture' OR app = 'gallery' OR app = 'file'

И удаляю все найденные строки.

  1. Вызываем makemigration для формирования 0001_initial.py (при этом понимаем, что придётся восстановить таблицу с помощью sql команд).
  2. Вызываем migrate и смотрим, что в базе данных создалась таблица projects_project с правильной структурой данных.
  3. Пишем sql код переноса данных из projects_project_old в projects_project:
INSERT INTO projects_project(id, link, hint, "order", is_border, border_color) select id, link, title_in_link, "order", 'FALSE', border_color from projects_project_old;

Проанализируйте пример: как видите, идёт соответствие полей для заполнения. В интернете качественного примера я не нашёл, поэтому-то и родился сей пост, чтобы это дело восполнить :)

Обратите внимание, что border_width мы можем не заполнять, так как оно может быть пустым, а is_border мы должны заполнить, но, так как у нас нет информации об этом поле, то самое простое - это заполнить значением FALSE для каждой записи. Как вариант потом можно написать django миграцию для заполнения полей TRUE или FALSE в зависимости от наличия какого-либо значения в поле border_color, но это уже другая история.

Ещё обратите внимание на то, что поле order совпадает со служебным словом sql, поэтому нужно это поле обособить двойными кавычками.

  1. Удаляем таблицу projects_project_old.

Вот, и всё. Ещё раз повторюсь, этот пример для тех, кто случайно сломал структуру данных таблицы, или миграции поломал или, таким образом как я, удалял зависимости от приложения. Это долгий "sql-ручной" путь исправления структуры, поэтому прежде чем удалять миграции, попробуйте их просто поправить :)

Перенос данных связанных таблиц

Допустим есть таблица: gallery и picture. Таблица picture содержит внешний ключ на таблицу gallery.

Этот случай немного по сложнее: при попытке выполнить 4 шаг описанный выше django скорее всего будет ругаться примерно так:

django.db.utils.ProgrammingError: relation "gallery_picture_6d994cdb" already exists

Для решения проблемы нужно переименовать индекс:

ALTER INDEX public.gallery_picture_6d994cdb
  RENAME TO gallery_picture_old_6d994cdb;

Это можно сделать через графический интерфейс pgadmin:

Изменение индекса в pgadmin

Нужный нам индекс выделен зелёным. Теперь правой кнопкой мыши по щелчку на индекс вызываем контекстное меню и выбираем свойства:

Изменение индекса в pgadmin

Здесь нужно переименовать индекс, например, дописав "_old".

Теперь снова пытаемся выполнить шаг 4 и далее следуем остальным выше описанным шагам.

Оцените статью

0 из 5 (всего 0 оценок)

Поля, отмеченные звёздочкой ( * ) , являются обязательными.

Спасибо за ваш отзыв!

После нажатия кнопки "Отправить" ваше сообщение будет доставлено мне на почту.

Автор статьи

Права на использование материала, расположенного на этой странице http://vivazzi.pro/it/sql-move-data-in-different-tables/:

Разрешается копировать материал с указанием её автора и ссылки на оригинал без использования параметра rel="nofollow" в теге <a>. Использование:

Автор статьи: Мальцев Артём
Ссылка на статью: <a href="http://vivazzi.pro/it/sql-move-data-in-different-tables/">http://vivazzi.pro/it/sql-move-data-in-different-tables/</a>

Подробнее: Правила использования сайта

Комментариев: 0

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

Чтобы оставить комментарий от своего имени войдите или зарегистрируйтесь обычным способом или через социальные сети:

Отправить

На данный момент нет специального поиска, поэтому я предлагаю воспользоваться обычной поисковой системой, например, Google, добавив "vivazzi" после своего запроса.

Попробуйте