Закрыть

Для эффективной работы на сайте используются cookie и обработка персональных данных. Пользуясь этим сайтом, вы соглашаетесь с правилами использования сайта. Подробнее

Цитата дня

Vivazzi.ru

Личный сайт Мальцева Артема

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

Чак Норрис

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.ru/it/sql-move-data-in-different-tables/:

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

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

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

Вам нужно саморазвиваться или вы хотите зарабатывать деньги?

Или вы ищите хорошие IT сервисы или книги? Сохраните свое время и взгляните на мою подборку рекомендаций, которыми постоянно пользуюсь.
Посмотреть рекомендации

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

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

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

Отправить

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

Попробуйте