PostgreSQL: Executando DDL em todos os esquemas

8

Eu tenho uma configuração de banco de dados de vários inquilinos e preciso adicionar algumas colunas. Estou usando esquemas (e caminho_de_pesquisa) para particionar meus usuários, por isso estou procurando uma maneira onipresente de aplicar uma alteração no esquema DDL a todos os meus bancos de dados. Inicialmente, pensei que poderia fazê-lo como uma única consulta (cursor em pg_catalog), mas pensar em uma chamada de linha de comando psql -fpode ser a maneira preferida.

Chris
fonte
@RolandoMySQLDBA: em Postgresvez de PostgreSQLestá perfeitamente bem.
a_horse_with_no_name

Respostas:

11

Eu preferiria a última solução. Você pode coletar os nomes dos esquemas em um arquivo (um esquema por linha) em 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

Então você pode facilmente fazer o seguinte:

Ter um script de alteração de DDL (por exemplo change_schema.sql), sem referência ao esquema de inclusão

SET search_path TO :schema;

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

Em seguida, você pode transformar todas as linhas da lista de esquemas em uma linha como

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

com um sedcomando simples , por exemplo - basta executar esses comandos. Obviamente, você pode transformá-lo em um shell script adequado, se quiser.

dezso
fonte
11
É assim que eu faria também, embora usasse o shell para percorrer a lista de esquemas, em vez de sedê-lo, para ter uma melhor manipulação de erros. Apenas para completar, a outra abordagem seria escrevê-lo como um procedimento PL / PgSQL que costumava EXECUTEexecutar as instruções como SQL dinâmico.
Craig Ringer
9

Apenas para completar, outra abordagem é fazer um loop em todos os esquemas e executar a alteração com SQL dinâmico no PL / PgSQL, por exemplo:

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;
Craig Ringer
fonte