PostgreSQL:在每个模式上执行 DDL

Chr*_*ris 8 postgresql postgresql-9.2

我有一个多租户数据库设置,需要添加一些列。我正在使用模式(和 search_path)来划分我的用户,所以我正在寻找一种普遍存在的方法来将 DDL 模式更改应用于我的所有数据库。最初,我认为我可以将其作为单个查询(pg_catalog 上的光标)来执行,但认为命令行调用psql -f可能是首选方式。

dez*_*zso 11

我更喜欢后一种解决方案。您可以将架构名称收集到以下文件中(每行一个架构)psql

\o change_schema.sql
\t on

SELECT n.nspname
FROM pg_catalog.pg_namespace n
WHERE n.nspname !~ '^pg_' AND n.nspname <> 'information_schema';

-- reset the output
\o
\t off
Run Code Online (Sandbox Code Playgroud)

然后您可以轻松地执行以下操作:

有一个 DDL 更改脚本(例如,change_schema.sql),而不参考包含架构

SET search_path TO :schema;

BEGIN;
...
...
ALTER TABLE orders
ADD COLUMN last_modified timestamp;
...
...
COMMIT;
Run Code Online (Sandbox Code Playgroud)

然后你可以把模式列表的每一行变成一行

psql -h dbhost -d targetdb -f change_schema.sql -v schema=<schema_name>
Run Code Online (Sandbox Code Playgroud)

sed例如,使用一个简单的命令 - 那么你只需要运行这些命令。当然,如果您愿意,您可以将其转换为适当的 shell 脚本。


Cra*_*ger 10

为了完整起见,另一种方法是遍历所有模式并在 PL/PgSQL 中使用动态 SQL 运行更改,例如:

DO
$$
DECLARE
    schemaname name;
BEGIN
   FOR schemaname IN SELECT nspname FROM pg_namespace WHERE nspname NOT LIKE 'pg_%' AND nspname <> 'information_schema' LOOP
       EXECUTE format('ALTER TABLE %I.my_table ADD COLUMN blah blah;', schemaname);
   END LOOP;
END;
$$ LANGUAGE plpgsql;
Run Code Online (Sandbox Code Playgroud)