PostgreSQL:在每个架构上执行DDL


8

我有一个多租户数据库设置,需要添加一些列。我正在使用架构(和search_path)对用户进行分区,因此我正在寻找一种无所不在的方法来对所有数据库应用DDL模式更改。最初,我以为我可以将其作为单个查询(在pg_catalog上为游标)来实现,但是认为命令行调用psql -f可能是首选方法。


@RolandoMySQLDBA:Postgres而不是PostgreSQL完全可以。
a_horse_with_no_name

Answers:


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

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

使用DDL更改脚本(例如,change_schema.sql),而不引用包含模式

SET search_path TO :schema;

BEGIN;
...
...
ALTER TABLE orders
ADD COLUMN last_modified timestamp;
...
...
COMMIT;

然后,您可以将架构列表的每一行变成类似

psql -h dbhost -d targetdb -f change_schema.sql -v schema=<schema_name>

sed例如,使用一个简单的命令-然后您只需要运行这些命令即可。当然,您可以根据需要将其转换为适当的Shell脚本。


1
尽管我会使用Shell 循环遍历架构列表,而不是sed'ing,但这也是我要做的事情,因此我可以更好地进行错误处理。仅出于完整性考虑,另一种方法是将其编写为PL / PgSQL过程,该过程用于EXECUTE将语句作为动态SQL运行。
Craig Ringer 2013年

9

为了完整起见,另一种方法是遍历所有模式并使用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;
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.