PostgreSQL: выполнение DDL для каждой схемы

8

У меня мультитенантная установка БД, и мне нужно добавить несколько столбцов. Я использую схемы (и search_path) для разделения своих пользователей, поэтому я ищу повсеместный способ применения изменения DDL-схемы ко всем моим базам данных. Первоначально я думал, что смогу сделать это как один запрос (курсор на pg_catalog), но psql -fпредпочел бы вызвать вызов командной строки .

Крис
источник
@RolandoMySQLDBA: Postgresвместо PostgreSQLсовершенно нормально.
a_horse_with_no_name

Ответы:

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команды - тогда вам просто нужно выполнить эти команды. Конечно, вы можете превратить его в правильный скрипт оболочки, если хотите.

Dezso
источник
1
Это то же самое, что и я, хотя я бы использовал оболочку для циклического перемещения по списку схем, а не для ее усреднения, поэтому у меня была лучшая обработка ошибок. Просто для полноты другой подход заключается в том, чтобы написать его как процедуру PL / PgSQL, которая использовалась EXECUTEдля запуска операторов в виде динамического SQL.
Крейг Рингер
9

Просто для полноты, другой подход состоит в том, чтобы перебрать все схемы и выполнить изменение с помощью динамического SQL в PL / PgSQL, например:

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;
Крейг Рингер
источник