CREATE RULE nome AS ON evento TO objeto [ WHERE condição ] DO [ INSTEAD ] ação onde ação pode ser: NOTHING | consulta | ( consulta ; consulta ... ) | [ consulta ; consulta ... ]
O nome da regra a ser criada.
Evento é um entre SELECT, UPDATE, DELETE e INSERT.
Objeto pode ser tabela ou tabela.coluna (Atualmente, somente a forma tabela está implementada).
Qualquer expressão condicional-booleana SQL. A expressão de condição não pode fazer referência a nenhuma tabela, exceto new e old.
A consulta (ou consultas) causadora da ação pode ser um dos comandos SQL SELECT, INSERT, UPDATE, DELETE, ou NOTIFY.
Dentro da condição e da ação os nomes especiais de tabela new e old podem ser usados para se referir aos valores da tabela referenciada (o objeto). O new é válido nas regras ON INSERT e ON UPDATE para se referir à nova linha sendo inserida ou atualizada. O old é válido nas regras ON UPDATE e ON DELETE para se referir à linha existente sendo atualizada ou excluída.
O sistema de regras do PostgreSQL permite a definição de uma ação alternativa a ser realizada para as inclusões, atualizações ou exclusões nas tabelas do banco de dados. As regras também são utilizadas para implementar as visões das tabelas.
A semântica de uma regra é que, no instante em que uma instância individual (linha) é acessada, incluída, atualizada ou excluída, existe uma instância antiga (para consultas, atualizações e exclusões) e uma instância nova (para inclusões e atualizações). Toda as regras para o tipo de evento indicado no objeto de destino indicado (tabela) são examinadas, em uma ordem não especificada. Se a condição especificada na cláusula WHERE (caso exista) for verdadeira, a parte ação da regra é executada. A ação é executada em vez da consulta original se INSTEAD for especificado; senão é executada após a consulta original no caso de ON INSERT, ou antes da consulta original nos casos de ON UPDATE e ON DELETE. Dentro da condição e da ação, os valores dos campos da instância antiga e/ou da instância nova são substituídos por old.nome_atributo e new.nome_atributo.
A parte ação da regra pode ser composta por uma ou mais consultas. Para escrever várias consultas deve-se colocá-las entre parênteses ou entre colchetes. Estas consultas serão realizadas na ordem especificada (enquanto que não há garantia sobre a ordem de execução de múltiplas regras para o objeto). A ação também pode ser NOTHING indicando nenhuma ação. Portanto, a regra DO INSTEAD NOTHING suprime a execução da consulta original (quando sua condição for verdadeira); uma regra DO NOTHING não tem utilidade.
A parte ação da regra executa com o mesmo identificador do comando e da transação do comando do usuário que causou sua ativação.
Atualmente, as regras ON SELECT devem ser regras incondicionais INSTEAD e devem possuir ações compostas por uma única consulta SELECT. Portanto, uma regra ON SELECT torna efetivamente a tabela objeto em uma visão, cujo conteúdo visível são as linhas retornadas pela consulta SELECT da regra em vez de qualquer outra coisa que tenha sido armazenada na tabela (se houver). É considerado um estilo melhor escrever um comando CREATE VIEW do que criar uma tabela real e definir uma regra ON SELECT para esta tabela.
O comando CREATE VIEW cria uma tabela fictícia (sem armazenamento subjacente) e associa uma regra ON SELECT a esta tabela. O sistema não permite atualizações na visão, porque sabe que não existe uma tabela real. Pode ser criada a ilusão de uma visão atualizável definindo-se regras para ON INSERT, ON UPDATE e ON DELETE (ou qualquer subconjunto destes comandos que for suficiente para atender as necessidades) para substituir as ações de atualização na visão por atualizações apropriadas em outras tabelas.
Existe um problema quando se tenta utilizar regras condicionais para a atualização das 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á rejeitando as tentativas de realizar uma ação de atualização, porque poderá tentar realizar a ação sobre a tabela fictícia em alguns casos. Se for desejado tratar todos os casos válidos através de regras condicionais, pode-se simplesmente adicionar 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 como não INSTEAD; nos casos em que forem disparadas, vão se adicionar às ações padrão INSTEAD NOTHING.
É necessário possuir uma concessão para definição de regras na tabela para poder definir uma regra para a tabela. Use o comando GRANT e REVOKE para conceder e revogar as permissões.
É muito importante tomar cuidado para evitar as regras circulares. Por exemplo, embora qualquer uma destas duas definições de regra seja aceita pelo PostgreSQL, a consulta vai fazer com que o PostgreSQL retorne um erro porque a consulta vai circular muitas vezes:
CREATE RULE "_RETemp" AS ON SELECT TO emp DO INSTEAD SELECT * FROM toyemp; CREATE RULE "_RETtoyemp" AS ON SELECT TO toyemp DO INSTEAD SELECT * FROM emp;
A tentativa de consultar a tabela EMP faz com que o PostgreSQL emita um erro porque a consulta vai circular muitas vezes:
SELECT * FROM emp;
Atualmente, se uma regra possui uma consulta NOTIFY, o NOTIFY será executado incondicionalmente --- ou seja, a notificação será emitida mesmo que não existam linhas onde a regra possa ser aplicada. 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 de notificação (NOTIFY) será emitido durante a atualização (UPDATE), existindo ou não alguma linha com id = 42. Esta é uma restrição da implementação que deverá estar corrigida em versões futuras.