繁体   English   中英

在PostgreSQL数据库的所有模式中的表中添加一列

[英]Add a column to a table in all schemas of a PostgreSQL database

我有一个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;
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$

主要观点

  • 正如@Denis已经解释的那样 ,您可以使用DO语句遍历系统目录表上的条目。 但是,这需要Postgres 9.0或更高版本 您还可以创建一个函数 (也可以在8.4中使用 )。 DO语句默认使用过程语言plpgsql

  • 您唯一需要的系统目录是pg_namespace ,其中包含数据库的架构。 循环浏览除已知系统架构以外的所有架构。

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

  • 要向具有NOT NULL约束的表添加列,还必须提供用于填充新列的默认值。 在其他方面,这在逻辑上是不可能的。 我在您的陈述中添加了DEFAULT TRUE 根据您的需求调整。

  • 通过正确引用从系统目录表检索的标识符来避免SQL注入。 在这种情况下quote_ident() 还有更多选项(dba.SE上的相关答案)

  • 你需要动态SQL。 我的主要技巧是动态设置search_path ,因此可以反复运行相同的语句。 SET LOCAL的效果一直持续到事务结束。 如果需要在同一事务中执行更多操作(不太可能),可以使用RESET search_path或保存先前状态并重置它:

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

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM