Проблема с таблицей 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');