Подтвердить что ты не робот

Проблема с Postgres ALTER TABLE

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

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

4b9b3361

Ответ 1

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

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

Ответ 2

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

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

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 - это какая-то сумасшедшая постгрессивная вещь, +4 является обязательной.)

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

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

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

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

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

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

Ответ 3

Сегодня я столкнулся с этой проблемой и нашел работу, чтобы избежать сброса и воссоздания VIEW. Я не могу просто оставить свой просмотр, потому что это мастер VIEW, который имеет множество зависимых VIEW, построенных поверх него. Не имея пересоздания script для DROP CASCADE, а затем воссоздайте ВСЕ мои VIEW, это будет работать.

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

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 явный тип, который не изменяется. Поскольку мой VIEW использует '(base_table_field1 *.01):: numeric AS field1', он работает, но 'base_table_field1 AS field1' не будет потому, что тип столбца изменится. Этот подход может помочь в некоторых случаях, таких как мои.