Проблема с таблицей Postgres ALTER

У меня есть одна проблема с ALTER TABLE в postgre. Я хочу изменить размер столбца varchar. Когда я пытаюсь это сделать, он говорит, что представление зависит от этого столбца. Я не могу отбросить представление, потому что от него зависит что-то еще. Есть ли другой способ, кроме как отбросить все и воссоздать его снова?

Я только что нашел один вариант, который состоит в том, чтобы удалить объединение таблиц из представления, когда я не буду изменять возвращаемые столбцы, я могу это сделать. Но есть еще кое-что. взгляды, которые мне нужно изменить. Разве нет ничего, как я могу сказать, что его следует отложить и проверить с помощью commit?

4 ответов


я столкнулся с этой проблемой и не мог найти никакого способа обойти ее. К сожалению, насколько я могу судить, нужно отбросить представления, изменить тип столбца в базовой таблице, а затем воссоздать представления. Это может произойти полностью в одной транзакции.

отсрочка ограничения не применяется к этой проблеме. Другими словами, даже SET CONSTRAINTS ALL DEFERRED не влияет на это ограничение. Чтобы быть конкретным, отсрочка ограничения не применяется к проверке согласованности, которая печатает ERROR: cannot alter type of a column used by a view or rule при попытке изменить тип столбца, лежащего в основе представления.


Если вам не надо менять тип поля, но только его размер, этот подход должен работать:

начиная с этих таблиц:

CREATE TABLE foo (id integer primary key, names varchar(10));
CREATE VIEW voo AS (SELECT id, names FROM foo);

\d foo и \d voo оба показывают длину как 10:

id     | integer               | not null
names  | character varying(10) | 

теперь измените длины на 20 в pg_attribute стол:

UPDATE pg_attribute SET atttypmod = 20+4
WHERE attrelid IN ('foo'::regclass, 'voo'::regclass)
AND attname = 'names';

(Примечание: 20+4-это сумасшедшее наследие postgresql, +4 является обязательным.)

теперь \d foo показывает:

id     | integer               | not null
names  | character varying(10) | 

бонус: это было waaay быстрее, чем делать:

ALTER TABLE foo ALTER COLUMN names TYPE varchar(20);

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

источник и более полное объяснение: http://sniptools.com/databases/resize-a-column-in-a-postgresql-table-without-changing-data


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

Я изменяю свое основное представление, чтобы использовать фиктивное значение для оскорбительного столбца, изменил столбец в таблице и переключил свое представление обратно в столбец. Используя подстава вот так:

CREATE TABLE base_table
(
  base_table_id integer,
  base_table_field1 numeric(10,4)
);

CREATE OR REPLACE VIEW master_view AS 
  SELECT
    base_table_id AS id,
    (base_table_field1 * .01)::numeric AS field1
  FROM base_table;

CREATE OR REPLACE VIEW dependent_view AS 
  SELECT
    id AS dependent_id,
    field1 AS dependent_field1
  FROM master_view;

попытка изменить тип base_table_field1 следующим образом:

ALTER TABLE base_table ALTER COLUMN base_table_field1 TYPE numeric(10,6);

даст вам эту ошибку:

ERROR:  cannot alter type of a column used by a view or rule
DETAIL:  rule _RETURN on view master_view depends on column "base_table_field1"

если вы измените master_view, чтобы использовать фиктивное значение для столбца, как это:

CREATE OR REPLACE VIEW master_view AS 
  SELECT
    base_table_id AS id,
    0.9999 AS field1
  FROM base_table;

затем запустите alter:

ALTER TABLE base_table ALTER COLUMN base_table_field1 TYPE numeric(10,6);

и переключите ваш взгляд назад:

CREATE OR REPLACE VIEW master_view AS 
  SELECT
    base_table_id AS id,
    (base_table_field1 * .01)::numeric AS field1
  FROM base_table;

все зависит от того, имеет ли ваш master_view явный тип, который не изменяется. Поскольку мое представление использует '(base_table_field1 * .01):: numeric AS field1 "работает, но" base_table_field1 AS field1 " не будет, потому что тип столбца изменяется. Такой подход может помочь в некоторых случаях, подобных моему.


Я немного опоздал на вечеринку, но спустя годы после того, как этот вопрос был опубликован, блестящее решение было опубликовано через статью, на которую ссылаются ниже (не моя-я просто благодарен бенефициару его блеска).

Я только что проверил это на объекте, на который ссылаются (на первом уровне) в 136 отдельных представлениях, и на каждое из этих представлений ссылаются в других представлениях. Решение пришло в считанные секунды.

Итак, прочитайте эту статью и скопируйте и вставьте таблицу и два перечисленные функции:

http://mwenus.blogspot.com/2014/04/postgresql-how-to-handle-table-and-view.html

пример реализации:

alter table mdm.global_item_master_swap
alter column prod_id type varchar(128),
alter column prod_nme type varchar(512);

ERROR: невозможно изменить тип столбца, используемого представлением или подробностью правила: правило _RETURN на просмотр toolbox_reporting."Average_setcost" зависит от столбец "prod_id" ********** Ошибка **********

ошибка: невозможно изменить тип столбца, используемого представления или правило

а теперь для магии ниндзя PostgreSQL:

select util.deps_save_and_drop_dependencies('mdm', 'global_item_master_swap');


alter table mdm.global_item_master_swap
alter column prod_id type varchar(128),
alter column prod_nme type varchar(512);


select util.deps_restore_dependencies('mdm', 'global_item_master_swap');