2.8. Esquemas

Um agrupamento de banco de dados do PostgreSQL (instalação) contém um ou mais bancos de dados nomeados. Os usuários e os grupos de usuários são compartilhados por todo o agrupamento, mas nenhum outro dado é compartilhado por todos os bancos de dados. Todas as conexões dos clientes com o servidor podem acessar somente os dados de um único banco de dados, aquele que foi especificado ao estabelecer a conexão.

Nota: Os usuários de um agrupamento de bancos de dados não possuem, necessariamente, o privilégio de acessar todos os bancos de dados do agrupamento. O compartilhamento de nomes de usuários significa que não pode haver mais de um usuário com o mesmo nome, digamos, joel em dois bancos de dados do mesmo agrupamento; mas o sistema pode ser configurado para permitir que o usuário joel acesse somente um dos bancos de dados.

Um banco de dados contém um ou mais esquemas nomeados, os quais por sua vez contém tabelas. Os esquemas também contêm outros tipos de objetos nomeados, incluindo tipos de dado, funções e operadores. O mesmo nome de objeto pode ser utilizado em esquemas diferentes sem conflitos; por exemplo, tanto o esquema_1 quanto o meu_esquema podem conter uma tabela chamada minha_tabela sem que haja conflito. Ao contrário dos bancos de dados, os esquemas não são separados rigidamente: um usuário pode acessar objetos de vários esquemas no banco de dados ao qual está conectado, caso possua os privilégios necessários para fazê-lo.

Existem diversos motivos pelos quais a utilização de esquemas pode ser desejada:

Os esquemas são análogos a diretórios no nível do sistema operacional, exceto que os esquemas não podem ser aninhados.

2.8.1. Criação de esquema

Para criar um novo esquema deve ser utilizado o comando CREATE SCHEMA. O nome do esquema é escolhido livremente pelo usuário. Por exemplo:

CREATE SCHEMA meu_esquema;

Para criar ou acessar objetos em um esquema deve ser escrito um nome qualificado, composto pelo nome do esquema e da tabela separados por um ponto:

esquema.tabela

Na verdade, a sintaxe mais geral

banco_de_dados.esquema.tabela

também pode ser utilizada, mas atualmente é apenas uma conformidade pró-forma com o padrão SQL; se for escrito o nome do banco de dados, este deverá ser o mesmo nome do banco de dados ao qual se está conectado.

Portanto, para criar uma tabela no novo esquema deve ser utilizado o comando:

CREATE TABLE meu_esquema.minha_tabela (
 ...
);

Esta forma funciona em qualquer lugar onde um nome de tabela é esperado, inclusive nos comandos de modificação de tabela e nos demais comandos de acesso a dados discutidos nos próximos capítulos.

Para excluir um esquema vazio (todos seus objetos já foram excluídos), deve ser utilizado o comando:

DROP SCHEMA meu_esquema;

Para excluir um esquema juntamente com todos os objetos que este contém, deve ser utilizado o comando:

DROP SCHEMA meu_esquema CASCADE;

Consulte a Seção 2.10 para ver a descrição do mecanismo geral por trás desta operação.

Muitas vezes deseja-se criar um esquema cujo dono é outro usuário (porque este é um dos modos utilizados para restringir as atividades dos usuários a espaços de nomes bem definidos). A sintaxe para esta operação é:

CREATE SCHEMA nome_do_esquema AUTHORIZATION nome_do_usuário;

Pode inclusive ser omitido o nome do esquema, e neste caso o nome do esquema será o mesmo nome do usuário. Consulte a Seção 2.8.6 para ver como isto pode ser útil.

Os nomes de esquemas começando por pg_ são reservados para uso pelo sistema, não devendo ser utilizados pelos usuários.

2.8.2. O esquema público

Nas seções anteriores foram criadas tabelas sem que fosse especificado nenhum nome de esquema. Por padrão, estas tabelas (e outros objetos) são automaticamente colocadas no esquema chamado public. Todo banco de dados novo possui este esquema. Portanto, as duas formas abaixo são equivalentes:

CREATE TABLE produtos ( ... );

e

CREATE TABLE public.produtos ( ... );

2.8.3. O caminho de procura do esquema

Os nomes qualificados são desagradáveis de escrever sendo melhor, geralmente, não ficar preso a um determinado esquema em uma aplicação. Portanto, as tabelas são geralmente referenciadas por meio de nomes não qualificados, composto apenas pelo nome da tabela. O sistema determina qual tabela está sendo referenciada seguindo o caminho de procura, o qual é uma lista de esquemas a ser pesquisados. A primeira tabela correspondente no caminho de procura é assumida como sendo a desejada. Não havendo nenhuma correspondência no caminho de procura ocasiona erro, mesmo que a tabela correspondente exista em outro esquema deste banco de dados.

O primeiro esquema nomeado do caminho de procura é chamado de esquema corrente. Além de ser o primeiro esquema a ser pesquisado, também é o esquema no qual as novas tabelas serão criadas se o comando CREATE TABLE não especificar o nome do esquema.

Para ver o caminho de procura corrente deve ser utilizado o comando:

SHOW search_path;

Na configuração padrão este comando retorna:

 search_path
--------------
 $user,public

O primeiro elemento especifica que o esquema cujo nome é o mesmo nome do usuário corrente deve ser pesquisado. Uma vez que este esquema ainda não foi criado, esta entrada é ignorada. O segundo elemento se refere ao esquema público visto anteriormente.

O primeiro esquema existente no caminho de procura é o local padrão para a criação dos novos objetos. Esta é a razão pela qual os objetos padrão são criados no esquema público. Quando os objetos são referenciados em qualquer outro contexto sem que haja qualificação pelo esquema (comandos de modificação de tabelas, modificação de dados ou consultas) o caminho de procura é percorrido até que o objeto correspondente seja encontrado. Portanto, na configuração padrão, qualquer acesso não qualificado somente pode fazer referência ao esquema público.

Para incluir o novo esquema no caminho deve ser utilizado o comando:

SET search_path TO meu_esquema,public;

O esquema $user foi omitido porque não há necessidade imediata dele. Fazendo isto, as tabelas do esquema meu_esquema podem ser acessadas sem serem qualificadas pelo esquema:

DROP TABLE minha_tabela;

Novamente, uma vez que meu_esquema é o primeiro elemento do caminho, os novos objetos serão criados neste esquema por padrão.

Também é possível escrever

SET search_path TO meu_esquema;

para retirar o acesso ao esquema público, a não ser que seja feita uma qualificação explícita deste esquema. Não existe nada em especial com relação ao esquema público, a não ser que existe por padrão. Também pode ser excluído.

Veja também a Seção 6.13 para ver outras formas de acessar o caminho de procura de esquema.

O caminho de procura funciona para nomes de tipos de dado, nomes de funções e nomes de operadores do mesmo modo que funciona para nomes de tabelas. Os tipos de dado e os nomes de funções podem ser qualificados do mesmo modo que os nomes das tabelas. Se for necessário escrever um nome qualificado de operador na expressão existe um modo especial para fazê-lo: deve ser escrito

OPERATOR(esquema.operador)

Isto é necessário para evitar uma sintaxe ambígua. Um exemplo pode ser

SELECT 3 OPERATOR(pg_catalog.+) 4;

Na prática confia-se no caminho de procura para os operadores, não havendo necessidade de escrever nada tão feio assim.

2.8.4. Esquemas e privilégios

Por padrão, os usuários não conseguem enxergar os objetos dos esquemas que não possuem. Para poderem enxergar, o dono do esquema deve conceder o privilégio USAGE para o esquema. Para permitir os usuários utilizarem os objetos do esquema é necessário conceder privilégios adicionais, apropriados para cada objeto.

Também pode ser permitido que um usuário crie objetos no esquema de outro usuário. Para permitir que isto seja feito deve ser concedido o privilégio CREATE para o esquema. Observe que por padrão todos possuem o privilégio CREATE para o esquema public. Isto permite a todos os usuários que podem se conectar ao banco de dados criar objetos neste banco de dados. Se isto não for desejado, este privilégio pode ser revogado:

REVOKE CREATE ON public FROM PUBLIC;

O primeiro "public" acima é o nome do esquema, enquanto o segundo "PUBLIC" significa "todos os usuários". Na primeira ocorrência é um identificador, enquanto na segunda ocorrência é uma palavra reservada. Por isso, na primeira vez está escrito em minúsculas enquanto na segunda vez está em maiúsculas; lembre-se da convenção da Seção 1.1.1.

2.8.5. O esquema do catálogo do sistema

Além do esquema public e dos esquemas criados pelos usuários, cada banco de dados possui um esquema chamado pg_catalog, contendo as tabelas do sistema e todos os tipos de dado, funções e operadores nativos. O pg_catalog é sempre uma parte efetiva do caminho de procura. Se não for colocado explicitamente no caminho de procura, então é implicitamente procurado antes dos esquemas do caminho de procura. Isto garante que os nomes nativos sempre poderão ser encontrados. Entretanto, é possível colocar explicitamente o pg_catalog no final do caminho de procura, se for desejado que os nomes definidos pelo usuário prevaleçam sobre os nomes nativos.

Nas versões do PostgreSQL anteriores a 7.3, os nomes das tabelas começando por pg_ eram reservados. Isto não é mais verdade: estas tabelas podem ser criadas em qualquer esquema que não seja o do sistema. Entretanto, é melhor continuar evitando estes nomes, para garantir que não haverá conflito caso alguma versão futura defina um catálogo do sistema com o mesmo nome da tabela criada (com o caminho de procura padrão, uma referência não qualificada à tabela criada será resolvida por um catálogo do sistema). Os catálogos do sistema vão continuar utilizando a convenção de possuir nomes começando por pg_, não havendo conflito com os nomes não qualificados das tabelas dos usuários, desde que os usuários evitem utilizar o prefixo pg_.

2.8.6. Formas de utilização

Os esquemas podem ser utilizados para organizar os dados de várias maneiras. Existem algumas formas de utilização recomendadas e que são facilmente suportadas pela configuração padrão:

2.8.7. Portabilidade

No padrão SQL, a noção de objetos no mesmo esquema possuídos por usuários diferentes não existe. Além disso, algumas implementações não permitem a criação de esquemas com nome diferente do nome do seu dono. Na verdade, os conceitos de esquema e de usuário são praticamente equivalentes em sistemas de banco de dados que implementam apenas o suporte ao esquema básico especificado no padrão. Portanto, muitos usuários consideram os nomes qualificados na verdade compostos por nome_do_usuário.nome_da_tabela. Esta é a forma como o PostgreSQL se comportará efetivamente se for criado um esquema por usuário para todos os usuários.

Além disso, não existe o conceito do esquema public no padrão SQL. Para uma conformidade total com o padrão não deve ser utilizado (talvez deva até ser removido) o esquema public.

Obviamente, alguns sistemas de banco de dados SQL podem não implementar esquemas de nenhuma maneira, ou oferecer suporte a espaços de nomes permitindo apenas um acesso (possivelmente limitado) entre bancos de dados. Se for necessário trabalhar com estes sistemas, o máximo de portabilidade é obtido não utilizando nada relacionado aos esquemas.