【问题标题】:Add a column to a table in all schemas of a PostgreSQL database向 PostgreSQL 数据库的所有模式中的表添加列
【发布时间】:2013-11-28 19:04:32
【问题描述】:

我有一个 Postgres 8.4 架构,如下所示:

My_Database
 |-> Schemas
       |-> AccountA
       |-> AccountB
       |-> AccountC
       |-> AccountD
       |-> AccountE
      ...
       |-> AccountZ

所有模式都有一个名为product 的表,我想立即向它们添加一个布尔列。可以这样做吗?

到目前为止,我发现的唯一方法是逐个帐户运行以下 SQL 帐户。

ALTER TABLE product ADD COLUMN show_price boolean NOT NULL DEFAULT TRUE;

【问题讨论】:

    标签: sql postgresql plpgsql ddl postgresql-8.4


    【解决方案1】:
    DO
    $do$
    DECLARE
      _schema text;
      _sp
    BEGIN
       FOR _schema IN
          SELECT quote_ident(nspname)  -- prevent SQL injection
          FROM   pg_namespace n
          WHERE  nspname !~~ 'pg_%'
          AND    nspname <>  'information_schema'
       LOOP
          EXECUTE 'SET LOCAL search_path = ' || _schema;
          ALTER TABLE product ADD COLUMN show_price boolean NOT NULL DEFAULT TRUE;
       END LOOP;
    END
    $do$
    

    您可以使用DO statement 遍历系统目录表中的条目。需要 Postgres 9.0 或更高版本
    你也可以create a functionDO 语句默认使用procedural language plpgsql

    您需要的唯一系统目录是pg_namespace,它包含数据库的模式。循环遍历除已知系统架构之外的所有架构。

    确保您连接到正确的数据库!

    要将列添加到具有 NOT NULL 约束的表中,您还必须提供默认值来填充新列。否则逻辑上不可能。我添加了DEFAULT TRUE,根据您的需要进行调整。

    通过正确引用从系统目录表中检索到的标识符来避免 SQL 注入。 quote_ident() 在这种情况下。 [还有更多选择。见:

    您需要动态 SQL。主要的“技巧”是动态设置search_path,因此可以一遍又一遍地运行相同的语句。 SET LOCAL 的效果一直持续到交易结束。你可以使用RESET search_path 或者保存之前的状态,如果你需要在同一个事务中做更多的事情(不太可能):

    SHOW search_path INTO _text_var;
    ...
    EXECUTE 'SET search_path = ' || _text_var;
    

    【讨论】:

      【解决方案2】:

      无论如何你都需要这样做。

      您可以通过查询目录来自动化它,然后将代码包装在 do block(在 Postgres 9.0 或更高版本中)或使用迁移脚本中。如果您不熟悉查询目录,要找到所需的查询,最简单的方法是使用psql -E。它会显示当您输入 \dn\dt 时运行的隐藏查询。

      【讨论】:

        猜你喜欢
        • 2021-06-08
        • 2013-06-11
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-09-15
        • 1970-01-01
        • 2010-11-23
        • 1970-01-01
        相关资源
        最近更新 更多