PostgreSQL: удалить столбец из поля зрения


10

У меня есть место, VIEWгде я пытаюсь создать скрипт развития, чтобы я мог добавить к нему столбец. Эта часть отлично работает; колонка добавлена ​​просто отлично. Однако обратное не работает; удалить последний добавленный столбец не удастся с ERROR: cannot drop columns from viewсообщением. Проблема в том, что этот конкретный взгляд имеет много ссылок, как от, так и к, поэтому я не могу просто DROP CASCADEпроклясть!

Есть ли причина, по которой я не могу удалить недавно добавленный столбец из заданного VIEW? Тогда, что я могу сделать, чтобы выполнить эту задачу?

(Примечание: обстоятельства здесь такие, какие есть, но я очень хорошо вижу похожую ситуацию, во многих других случаях, например, отбрасывание столбца из представления.)


Как вы добавили колонку в первую очередь? Вы не можете ALTER VIEW ... ADD COLUMN. Вы используете CREATE OR REPLACE VIEW? Покажите свой код, пожалуйста.
Крейг Рингер,

@CraigRinger, да, CREATE OR REPLACE VIEWс тем же значением def, за исключением дополнительного столбца (поскольку в таблицу ref'ed добавлен новый столбец, поэтому представление должно включать его). «Деволюция» удаляет столбец из таблицы ref'ed, поэтому VIEWон также не должен больше его возвращать.
Яник Рошон

Ответы:


13

PostgreSQL (с версией не ниже 9.4) в настоящее время не поддерживает удаление столбца с помощью CREATE OR REPLACE VIEW.

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

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

CREATE OR REPLACE VIEWпришлось бы рекурсивно сканировать все зависимости и убедиться, что ни одна из них не ссылалась на столбец, который нужно удалить. Если бы они использовали SELECT *его, ему пришлось бы удалить столбец из раскрытия *в зависимости, а затем просканировать его зависимости. Для этого необходимо проделать немалую работу, и есть некоторые области, где неясно, как именно должен вести себя отбрасывание столбца, особенно когда речь идет о взаимодействиях с dump и reload. Так что никто не хотел, чтобы эта функция была достаточно реализована. Патчи и / или спонсорство разработки приветствуются.

Вам придется отбросить представление и все, что от него зависит, а затем заново создать его и его зависимости. (То же самое использовалось для добавления столбца в представление; поддержка добавления столбцов была введена в 8.4).

Обратите внимание, что в целом не ожидается, что DDL будет обратимым. Понятие «деволюции» действительно ошибочно. Например, если вы отбрасываете столбец, а затем добавляете его снова, данные по-прежнему исчезают.


1
Итак, что вы говорите, что, когда крупному приложению со сложными отношениями необходимо изменить столбец, необходимо воссоздать весь (или, по крайней мере, большую часть) DDL? У меня нет большого опыта работы с Postgre, но, исходя из mySQL, у меня никогда не возникало подобных проблем (с Oracle, SQL Server или MySQL), и мне кажется странным, что изменение не может быть просто выполнено и произойдет ошибка (если любой) быть брошенным во время выполнения вместо этого. Это ограничение является довольно ограничительным.
Яник Рошон

@YanickRochon Да, это боль, и я бы хотел, чтобы она улучшилась. Если вы хотите помочь сделать это, подумайте о финансировании работы над этим; см. postgresql.org/support/professional_support .
Крейг Рингер,

Мы слишком малы, чтобы финансировать такое предприятие. Но рад видеть, что это не фиксированная тема.
Яник Рошон

1
@YanickRochon Достаточно справедливо. Это в TODO - «разрешить перекомпиляцию представления / правила при изменении базовой таблицы», wiki.postgresql.org/wiki/Todo#Views_and_Rules .
Крейг Рингер,
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.