如果从 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个回答
0
投票

您不能

DELETE
information schema 中任何视图的行。出于多种原因,这将是无稽之谈。作为记录,信息模式中的视图 not system catalogs 的一部分。但是您也不要直接弄乱系统目录——即使这可能是可能的。一个错误的举动,你可以破坏你的数据库(集群)。使用专用的 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_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 12 中添加的。您可以对旧版本中的函数执行相同的操作。参见:

这种动态 SQL 的基础知识:

在我们检查该列是否存在后,添加

IF EXISTS
似乎有点矫枉过正。仅当多个事务可能同时操作列时才有意义,这似乎是一个非常奇怪的情况。

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