Я использую Postgres 14. Я знаю о ALTER TABLE DROP COLUMN. Но этот вариант в моем случае не работает.
Равны ли эти два запроса:
ALTER TABLE <some_table_1>
DROP COLUMN IF EXISTS <column_1>,
DROP COLUMN IF EXISTS <column_2>;
ALTER TABLE <some_table_2>
DROP COLUMN IF EXISTS <column_1>,
DROP COLUMN IF EXISTS <column_2>;
И
DELETE FROM information_schema.columns
WHERE table_name IN (<some_table_1>, <some_table_2>)
AND column_name IN (<column_1>, <column_2>)
Или ALTER TABLE выполняет дополнительную работу? Я хочу использовать DELETE FROM, потому что мне действительно нужны такие фильтры, как WHERE в удалении столбцов.
у меня ошибка Views that do not select from a single table or view are not automatically updatable.
Правильно, так что ваш вопрос спорный; невозможно выполнить код, о последствиях которого вы спрашиваете. Кроме того, вам никогда не следует даже думать о взломе таблиц каталога. Используйте API, предоставленный для задачи, то есть оператор alter.
Какие фильтры вам нужны для удаления столбцов? Вместо того, чтобы просто заявить, что конкретный вариант не подходит для ваших нужд, постарайтесь объяснить требования и причины, по которым этот вариант неприемлем. Если бы оператор DELETE был исполняемым, он был бы функционально идентичен паре операторов ALTER TABLE, поэтому ничто в вопросе не демонстрирует обоснования отказа от операторов ALTER TABLE.





Вы не можете DELETE строки из любого представления в информационной схеме . Это было бы нонсенсом по многим причинам. К сведению, представления в информационной схеме не являются частью системных каталогов. Но вы также не связываетесь напрямую с системными каталогами, даже если это возможно. Одно неверное движение, и вы можете сломать свою базу данных (кластер). Используйте специальные команды DDL.
Вы ищете динамический SQL, который может быть основан либо на информационной схеме, либо на системных каталогах. У каждого есть плюсы и минусы. Видеть:
В моей реализации используются системные каталоги:
CREATE OR REPLACE PROCEDURE public.my_column_drop(_tbls text[]
, _cols text[]
, _schema text = 'public')
LANGUAGE plpgsql AS
$proc$
DECLARE
_tbl regclass;
_drops text;
BEGIN
FOR _tbl IN
SELECT c.oid
FROM pg_catalog.pg_class c
WHERE c.relkind = 'r' -- only plain tables (?)
AND c.relnamespace = _schema::regnamespace
AND c.relname = ANY (_tbls)
-- more filters HERE
LOOP
-- RAISE NOTICE '%', _tbl;
SELECT INTO _drops
string_agg(format('DROP COLUMN IF EXISTS %I', a.attname), ', ')
FROM pg_catalog.pg_attribute a
WHERE a.attrelid = _tbl
AND a.attname = ANY (_cols)
AND NOT a.attisdropped
AND a.attnum > 0
-- more filters HERE
;
IF _drops IS NOT NULL THEN
-- RAISE NOTICE '%', concat_ws(' ', 'ALTER TABLE', _tbl, _drops);
EXECUTE concat_ws(' ', 'ALTER TABLE', _tbl, _drops);
ELSE
RAISE NOTICE 'Table % has no candidate columns', _tbl;
END IF;
END LOOP;
END
$proc$;
Вызов:
CALL public.my_column_drop ('{some_table_1,some_table_2}', '{column_1, column_2}');
Попытка удалить столбцы завершается неудачно, если есть какие-либо зависимости. Моя простая функция не проверяет их. Вам нужно будет определить, что проверять и что делать в случае зависимостей...
Процедуры были добавлены в Postgres 11. Вы можете сделать то же самое с функцией в более старых версиях. Или с помощью команды DO для одноразового использования в любой версии. Видеть:
Основы для такого динамического SQL:
Добавление IF EXISTS кажется излишним после того, как мы проверили существование столбца. Имеет смысл только в том случае, если несколько транзакций могут одновременно манипулировать столбцами, что кажется крайне странным случаем.
Что происходит, когда вы пытаетесь это сделать?