Проблема с Postgres ALTER TABLE
У меня есть одна проблема с ALTER TABLE в postgre. Я хочу изменить размер столбца varchar. Когда я пытаюсь это сделать, он говорит, что представление зависит от этого столбца. Я не могу отказаться от представления, потому что от него зависит что-то другое. Есть ли другой способ, чем сбросить все и снова создать его снова?
Я только что нашел один вариант, который заключается в том, чтобы удалить таблицу, соединяющуюся с представлением, когда я не буду изменять возвращаемые столбцы, я могу это сделать. Но тем не менее, есть больше взглядов, которые мне нужно будет изменить. Разве нет ничего, как я могу сказать, что его следует отложить и проверить с фиксацией?
Ответы
Ответ 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' не будет потому, что тип столбца изменится. Этот подход может помочь в некоторых случаях, таких как мои.