如果我从 information_schema.columns 中删除某列,该列是否会被删除?

问题描述 投票:0回答:1

我使用 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
这样的过滤器来删除列。

postgresql dynamic-sql alter-table information-schema postgres-14
1个回答
4
投票

您无法从

信息模式
中的任何视图中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

命令在任何版本中一次性使用。参见:

Postgres 中存储过程是否在数据库事务中运行?

表名作为 PostgreSQL 函数参数

© www.soinside.com 2019 - 2024. All rights reserved.