postgres postgresql schema namespace search_path

Schemas

Um schema (também chamado de namespace) é uma separação lógica dos objetos do banco de dados. Assim como arquivos não estão todos na raiz de um sistema de arquivos, mas sim organizados em diretórios, também objetos (tabelas, visões…) do banco de dados são colocados em espaços próprios. Dessa forma, o usuário pode trabalhar com um conjunto de objetos de cada vez, alcançando maior produtividades em tarefas como exportação e importação de dados, movimentação de objetos entre tablespaces, mapeamento de schemas remotos, alteração de permissões em lote, entre outras.

                     ┌───────────────────┐
╔════════════════════╡ instância/cluster ╞═════════════════════╗
║                    └───────────────────┘                     ║
╠═╡global/╞═══════╗  ╔═════════════════════════════════╡base/╞═╣
║                 ║  ║                                         ║
║     O     O     ║  ║ ┏┥banco de dados┝┓ ┏━┥banco de dados┝━┓ ║
║    ─┼─   ─┼─    ║  ║ ┃└┤postgres├────┘┃ ┃ ┌─┤schema├─────┐ ┃ ║
║     │     │     ║  ║ ┗━━━━━━━━━━━━━━━━┛ ┃ │ ☑ tabelas    │ ┃ ║
║    ╱ ╲   ╱ ╲    ║  ║ ┏┥banco de dados┝┓ ┃ │ ☑ índices    │ ┃ ║
║ ☑ usuários      ║  ║ ┃└┤template1├───┘┃ ┃ │ ☑ visões     │ ┃ ║
║ ☑ grupos        ║  ║ ┗━━━━━━━━━━━━━━━━┛ ┃ │ ☑ sequências │ ┃ ║
║ ☑ slots de      ║  ║ ┏┥banco de dados┝┓ ┃ │ ☑ …          │ ┃ ║
║ ☑ replicação    ║  ║ ┃└┤template0├───┘┃ ┃ └──────────────┘ ┃ ║
║ ☑ pg_control    ║  ║ ┗━━━━━━━━━━━━━━━━┛ ┗━━━━━━━━━━━━━━━━━━┛ ║
║                 ║  ║                                         ║
╠═════════════════╝  ╚═════════════════════════════════════════╣
║                                                              ║
╠═╡pg_wal/╞══════════════════════════╗     ╔══════╡pg_tblspc/╞═╣
║ ┌─────┐ ┌─────┐ ┌─────┐ ┌─────┐    ║     ║                   ║
║ │…++++│→│…++++│→│…++++│→│…++++│→…  ║     ║                   ║
║ └┤/…1├┘ └┤/…2├┘ └┤/…3├┘ └┤/…4├┘    ║     ║        │          ║
╚════════════════════════════════════╩═════╩════════╪══════════╝
                                                    │
                                                    ↓
                                                 ╔╡/…╞╗
                                                 ║    ║
                                                 ╚════╝

Quando uma consulta é enviada para execução, objetos são buscados nos schemas específicos mencionados, como em SELECT * FROM public.tabela, que busca a tabela do schema public.

Mas podemos omitir o schema da consulta, como em SELECT * FROM tabela. Nesse caso, o PostgreSQL vai buscar a tabela em uma lista de schemas chamada search_path e usar o primeiro objeto encontrado nos schemas dessa lista, exatamente como o seu shell percorre os diretórios da variável $PATH para buscar executáveis que foram mencionados sem o caminho completo.

O usuário pode consultar o valor do search_path com um SHOW:

[[local]:5432] postgres@postgres=# SHOW search_path;
╔═════════════════╗
║   search_path   ║
╠═════════════════╣
║ "$user", public ║
╚═════════════════╝

O valor "$user", public indica que um schema com o mesmo nome do usuário será consultado primeiro e então um schema com o nome public. Schemas que não existirem são ignorados.

O usuário pode mudar o valor de search_path para aquela sessão com um comando SET, o que não influencia outras sessões:

[[local]:5432] postgres@postgres=# SET search_path to financeiro, rh, public;

Ele também pode alterar permanentemente o valor search_path para um usuário:

[[local]:5432] postgres@postgres=# ALTER USER usuario SET search_path to financeiro, rh, public;

Ou o valor padão para todo usuário que se conectar ao banco de dados:

[[local]:5432] postgres@postgres=# ALTER DATABASE app SET search_path to financeiro, rh, public;

Da mesma forma que search_path é consultado para leitura e escrita de dados dos objetos, ele também é usado para a criação de objetos. Quando um objeto é criado sem mencionar o schema de destino, o primeiro schema existente da lista do search_path vai ser usado como destino. Então uma nova tabela financeiro.contas pode ser criada como:

[[local]:5432] postgres@postgres=# CREATE TABLE financeiro.contas ();

Ou como:

[[local]:5432] postgres@postgres=# SET search_path TO financeiro;
[[local]:5432] postgres@postgres=# CREATE TABLE contas ();