CREATE [ OR REPLACE ] RULE nome AS ON evento TO tabela [ WHERE condição ] DO [ INSTEAD ] { NOTHING | comando | ( comando ; comando ... ) }
O comando CREATE RULE cria uma regra aplicada à tabela ou visão especificada. O comando CREATE OR REPLACE RULE cria uma regra, ou substitui uma regra existente com mesmo nome, na tabela.
O sistema de regras do PostgreSQL permite definir uma ação alternativa a ser realizada nas inclusões, atualizações ou exclusões em tabelas do banco de dados. Sem entrar em detalhes, uma regra faz com que comandos adicionais sejam executados quando um determinado comando é executado em uma determinada tabela. Diferentemente, a regra INSTEAD pode substituir um determinado comando por outro, ou mesmo fazer com que o comando não seja executado. As regras também são utilizadas para implementar as visões das tabelas. É importante perceber que a regra é, na realidade, um mecanismo de transformação de comando, ou uma macro de comando. A transformação acontece antes do início da execução do comando. Se, na verdade, for desejada uma operação que dispare de forma independente para cada linha física, provavelmente o que se deseja é um gatilho, e não uma regra. Mais informações sobre o sistema de regras podem ser obtidas no Capítulo 34 .
Atualmente, as regras ON SELECT devem ser regras INSTEAD incondicionais, e devem possuir ações consistindo de um único comando SELECT. Portanto, uma regra ON SELECT tem por efeito transformar a tabela em uma visão, cujo conteúdo visível são as linhas retornadas pelo comando SELECT da regra, em vez do que está armazenado na tabela (se houver alguma coisa). É considerado um estilo melhor usar o comando CREATE VIEW do que criar uma tabela real e definir uma regra ON SELECT para a mesma.
É possível criar a ilusão de uma visão atualizável definindo regras ON INSERT, ON UPDATE e ON DELETE, ou qualquer subconjunto destas que seja suficiente para as finalidades desejadas, para substituir as ações de atualização na visão por atualizações apropriadas em outras tabelas.
Existe algo a ser lembrado quando se tenta utilizar regras condicionais para atualização de visões: é obrigatório haver uma regra incondicional INSTEAD para cada ação que se deseja permitir na visão. Se a regra for condicional, ou não for INSTEAD, então o sistema continuará a rejeitar as tentativas de realizar a ação de atualização, porque acha que poderá acabar tentando realizar a ação sobre a tabela fictícia da visão em alguns casos. Se for desejado tratar todos os casos úteis por meio de regras condicionais, deve ser adicionada uma regra incondicional DO INSTEAD NOTHING para garantir que o sistema sabe que nunca será chamado para atualizar a tabela fictícia. Em seguida devem ser criadas as regras condicionais não-INSTEAD; nos casos onde se aplicam, se adicionam à ação padrão INSTEAD NOTHING.
Dentro da condição e do comando, os nomes especiais de tabela NEW e OLD podem ser usados para fazer referência aos valores na tabela referenciada. O NEW é válido nas regras ON INSERT e ON UPDATE, para fazer referência à nova linha sendo inserida ou atualizada. O OLD é válido nas regras ON UPDATE e ON DELETE, para fazer referência à linha existente sendo atualizada ou excluída.
É necessário possuir o privilégio RULE na tabela para poder definir uma regra para a mesma.
É muito importante tomar cuidado para evitar regras circulares. Por exemplo, embora as duas definições de regra abaixo sejam aceitas pelo PostgreSQL, o comando SELECT faz com que o PostgreSQL relate um erro, porque a consulta vai circular muitas vezes:
CREATE RULE "_RETURN" AS ON SELECT TO t1 DO INSTEAD SELECT * FROM t2; CREATE RULE "_RETURN" AS ON SELECT TO t2 DO INSTEAD SELECT * FROM t1; SELECT * FROM t1;
Atualmente, se a ação da regra contiver um comando NOTIFY, este comando NOTIFY será executado incondicionalmente, ou seja, o NOTIFY será emitido mesmo não havendo nenhuma linha onde a regra se aplique. Por exemplo, em
CREATE RULE me_notifique AS ON UPDATE TO minha_tabela DO NOTIFY minha_tabela; UPDATE minha_tabela SET nome = 'foo' WHERE id = 42;
um evento NOTIFY será enviado durante o UPDATE, haja ou não alguma linha que corresponda à condição id = 42. Esta é uma restrição da implementação que deverá estar corrigida em versões futuras.