O sistema de regras (rule system) do PostgreSQL oferece grande flexibilidade quando é necessário implementar determinadas regras de negócio. Assim como os triggers, as rules, também chamadas de regras, são acionadas quando um determinado evento ocorrer em uma tabela. Esse evento pode ser:

  • INSERT
  • UPDATE
  • DELETE
  • SELECT

As ações resultantes de uma regra podem ser complementares ou em substituição ao comando que aciona uma regra. Com esse artigo, espera-se que o leitor fique habilitado para fazer o uso do sistema de rules do PostgreSQL para estender e dar mais flexibilidade às suas aplicações.

Create Rule in PostgreSQL

O comando responsável pela criação de uma rule é o CREATE RULE. Sua sintaxe é apresentada abaixo:


CREATE [ OR REPLACE ] RULE NomeDaRule AS ON evento
  TO Tabela [ WHERE CondiçãoLógica]
  DO [ ALSO | INSTEAD ] { NOTHING | comando | ( comando ; comando ... ) }

Onde:

  • NomeDaRule: indica qual evento está associado à regra. Os eventos podem ser: INSERT, UPDATE, DELETE e SELECT. Somente um evento pode ser definido.
  • Evento: indica qual evento está associado à regra. Os eventos podem ser: INSERT, UPDATE, DELETE e SELECT. Somente um evento pode ser definido.
  • Tabela: a tabela a qual a rule está associada.
  • CondiçãoLógica: uma condição que aciona a regra. Não é possível utilizar outras tabelas ou uma função de agregação.
  • ALSO e INSTEAD: indica se o comando que acionou a rule e os comandos definidos serão executados (ALSO) ou se o comando original será substituído (INSTEAD).
  • Comando: especifica o comando SQL a ser executado por essa rule. Uma rule do tipo SELECT não suporta mais de um comando. Entretanto, pode-se especificar mais de um comando colocando-os entre parênteses e separando-os por ponto-e-vírgula para os demais tipos.

NEW e OLD

O nome especial de tabela NEW pode ser utilizado para referenciar os novos valores inseridos (ON INSERT) ou atualizados (ON UPDATE) em uma tabela. Já nome especial OLD contém os valores apagados através de um DELETE ou UPDATE.

Exemplo:

Vamos criar uma rule de auditoria em uma tabela que mantém os dados de funcionários de uma empresa, como mostra a Figura 1. Nos exemplos utilizaremos as funções current_user, que retorna o usuário conectado ao banco de dados, e o current_timestamp, que retorna a data e a hora atual.

Estrutura da tabela de emp
Figura 1. Estrutura da tabela de emp.

O primeiro passo é criar uma tabela de auditoria que será atualizada toda vez que o salário de um funcionário for modificado (Listagem 1). Essa tabela terá o número do funcionário (n_emp), o novo salário (novo_sal), o usuário que efetuou a alteração (usuario) e a data mais a hora em que a alteração ocorreu (datahora).


CREATE TABLE emp_log (

n_emp    int,

novo_sal decimal(10,2),

usuario  varchar(50),

datahora timestamp);
Listagem 1. Tabela

O comando para criação da rule é apresentado na Listagem 2.


CREATE RULE log_emp_rule AS ON UPDATE TO emp

WHERE NEW.sal <> OLD.sal

DO INSERT INTO emp_log

VALUES (NEW.n_emp, NEW.sal, current_user, current_timestamp);
Listagem 2. Criação de uma rule

Note que a parte em destaque na Listagem 2 nos mostra que essa regra só será acionada quando o salário novo (NEW.sal) e o salário antigo (OLD.sal) forem diferentes, indicando portanto, uma alteração no valor da coluna sal, que contém o salário dos funcionários.

O comando da Listagem 3 atualiza o salário de um determinado funcionário e aciona a regra log_emp_rule inserindo um novo registro na tabela de auditoria.


UPDATE emp SET sal = sal * 1.1

WHERE n_emp = 110;
Listagem 3. Acionando a rule log_emp_rule

Um detalhe importante é que caso exista mais de uma rule em uma tabela, a ordem de acionamento segue a ordem alfabética do nome das rules.

Substituindo comandos

Para substituir um comando original por aqueles definidos na ação de uma rule, basta utilizar a palavra-chave INSTEAD. A Listagem 4 mostra o comando da Listagem 2 reescrito.


CREATE RULE log_emp_rule AS ON UPDATE TO emp

  WHERE NEW.sal <> OLD.sal

    DO INSTEAD INSERT INTO emp_log VALUES (NEW.n_emp,

      NEW.sal, current_user, current_timestamp);
Listagem 4. Substituindo comandos

Essa nova regra define que o comando original de atualização que acionar a regra será ignorado, executando apenas o comando complementar definido.

Caso o comando de atualização (Listagem 3) seja executado, com essa nova regra, a tabela emp não será afetada, mas a tentativa de fazê-lo será gravada na tabela emp_log.

Ignorando comandos

Para ignorar o comando original e não definir ações complementares, pode-se utilizar a palavra-chave NOTHING em conjunto com o INSTEAD. A Listagem 5 mostra o comando da Listagem 2 reescrito.


CREATE RULE log_emp_rule AS ON UPDATE TO emp

WHERE NEW.sal <> OLD.sal

DO INSTEAD NOTHING;
Listagem 5. Ignorando comandos

Caso um comando acione essa regra, ele será ignorado sem gerar qualquer tipo de erro para o usuário, e as tabelas emp e emp_log não terão qualquer alteração.

Rules e views

As views são muito utilizadas para gravar no banco de dados uma consulta em uma ou mais tabelas para a visualização de dados. No PostgreSQL, as views podem ser implementadas utilizando o sistema de rules.


CREATE VIEW empv AS SELECT nome_emp, n_emp FROM emp;
Listagem 6. Criação de uma view

Apesar de não ser prático, a view criada na Listagem 6 também poderia ser criada com os dois passos apresentados na Listagem 7, que são exatamente as operações internas realizadas pelo PostgreSQL quando criamos uma view.


CREATE TABLE empv (nome_emp varchar(30), n_emp int);

CREATE RULE “_RETURN” AS ON SELECT TO empv 
DO INSTEAD SELECT nome_emp, n_emp FROM emp;
Listagem 7. Representação interna da criação de uma view

Views atualizáveis

Geralmente as views são utilizadas apenas para visualização de dados, não permitindo a execução de comandos como INSERT, UPDATE e DELETE. Entretanto, o recurso de views atualizáveis permite que essas modificações sejam refletidas na tabela a qual uma view está associada. A Listagem 8 mostra a implementação de uma view atualizável baseada na view da Listagem 6.


CREATE RULE empv_rule AS ON INSERT TO empv

DO INSTEAD INSERT INTO emp (n_emp, nome_emp, sal) 
VALUES (NEW.n_emp, NEW.nome_emp, NEW.sal);

O comando de inserção que for aplicado sobre a view será redirecionado para a tabela emp.

Apagando uma rule


DROP RULE NomeDaRule ON Tabela

Onde:

  • NomeDaRule: nome da rule que será apagada.
  • Tabela: nome da tabela onde a rule se encontra.

Triggers versus rules

Apesar de desempenharem papéis semelhantes, existem diferenças fundamentais entre rules e triggers. Portanto, é necessário escolher corretamente quando utilizar cada uma.

Quando uma rule é acionada, o comando que a acionou é reescrito ou um (ou mais) novo comando é gerado para executar os procedimentos definidos. A chamada da rule acontece antes da execução do comando original. Devido a esse comportamento, uma rule é acionada uma única vez, ao contrário dos triggers que são executados para cada linha afetada pelo comando que o disparou. Podemos pensar em triggers como uma reação à modificação dos dados de uma tabela. Normalmente esta reação é utilizada para implementar regras de negócio mais complexas. Vale lembrar que a funcionalidade rule é um recurso específico do PostgreSQL, dificultando o porte para outros bancos de dados.

Outra diferença está relacionada com a diversidade de comandos suportados. Em rules, só são permitidos comandos SQL, ao contrário dos triggers que possibilitam o uso das mais diversas linguagens procedurais suportadas pelo PostgreSQL, como: PL/pgSQL, C, Perl. Como regra geral, os triggers são indicados para as situações onde regras de negócio devem ser acionadas devido a certas modificações de dados.

Tabelas de sistema sobre rules

A view pg_rules contém informações das rules (Tabela 1). Existe também a tabela pg_rewrite que possui algumas informações mais detalhadas.

Nome Tipo Descrição
schemaname Name Schema que contém a tabela onde a regra se encontra.
tablename Name Nome da tabela onde a regra se encontra.
rulename Name Nome da regra.
definition Text Código fonte da regra.

Tabela 1. Campos da view pg_rules.

Conclusão

Apresentamos neste artigo um recurso pouco conhecido e, por isto, raramente utilizado do banco de dados PostgreSQL. Por se tratar de um recurso simples de implementar, uma vez que somente código SQL é utilizado, as rules são um complemento ao uso de triggers.

As rules podem criar novas possibilidades de modificar o comportamento de um comando SQL e também possibilitar o uso de funcionalidades novas sobre views, como atualização, remoção e inserção.

Conteúdos recentes

Saiba mais sobre Triggers e SQL Server ;)