2010-07-14 5 views
23

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

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

+1

скопируйте запрос вида и удалите его и внесите изменения в таблицу – TaherT

ответ

15

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

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

4

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

Я изменяю свой мастер 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 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' не будет потому, что тип столбца изменится. Такой подход может помочь в некоторых случаях, таких как мои.

+4

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

+3

Как это лучше, чем сбросить представление? Первая строка ... «это мастер VIEW, который имеет множество зависимых VIEW, построенных поверх него». То есть каскад каплируется и для этих зависимых представлений. –

7

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

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

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

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

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

Bonus: это было waaay быстрее, чем:

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

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

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

+7

Вы должны избегать изменения каталогов (например, pg_attribute) вручную, когда это возможно. Существует реальная опасность получить что-то неправильно и вызвать ошибки, включая сбои и повреждение данных, позже, когда вы меньше всего этого ожидаете. ТОЛЬКО делайте это в крайнем случае, ПОСЛЕ консультирования исходного кода, чтобы убедиться, что вы ничего не пропустили.Предложение об этом без каких-либо отказов является безответственным. – intgr

+0

Это то, как движок данных действительно работает за кулисами. Вы не меняете ТИП, но размер. Поскольку VARCHAR не вредит данным. +1 –

2

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

Я только что проверил это на объекте, на который ссылается (на первом уровне), в 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: cannot alter type of a column used by a view or rule DETAIL: rule _RETURN on view toolbox_reporting."Average_setcost" depends on column "prod_id" ********** Error **********

ERROR: cannot alter type of a column used by a view or rule

И теперь для магии 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'); 
+0

Ты - великая душа. – Vishnu