As regras definidas para os comandos INSERT,
UPDATE, e DELETE, são
muito diferentes das regras de visão descritas nas
seções anteriores.
Em primeiro lugar, o comando CREATE RULE permite
mais opções:
Permissão para não fazer nada.
Poder realizar múltiplas ações.
Poder ser INSTEAD ou
ALSO (o padrão).
As pseudo-relações NEW e
OLD tornam-se úteis.
Poder ter qualificações de regras.
Em segundo lugar, não modificam a árvore de consulta original. Em vez disso, criam zero ou mais novas árvores de consulta, e podem descartar a original.
Em muitos casos, tarefas que poderiam ser executadas por regras para
INSERT/UPDATE/DELETE
são melhor realizadas com gatilhos.
Os gatilhos são notacionalmente um pouco mais complicados, mas sua
semântica é muito mais simples de entender.
As regras tendem a ter resultados surpreendentes quando a consulta
original contém funções voláteis: as funções voláteis podem ser
executadas mais vezes do que o esperado no processo de execução
das regras.
Além disso, existem alguns casos sem suporte por estes tipos de
regras, incluindo cláusulas WITH na consulta
original, e subconsultas (em SELECT) na
lista SET de comandos UPDATE.
Isto acontece porque copiar estas construções em uma consulta de
regra resultaria em várias avaliações da subconsulta, contrariando
a intenção expressa do autor da consulta.
Tenha a sintaxe
CREATE [ OR REPLACE ] RULEnomeAS ONeventoTOnome_da_tabela[ WHEREcondição] DO [ ALSO | INSTEAD ] { NOTHING |comando| (comando;comando... ) }
em mente.
A seguir, regras de atualização significa
regras definidas para INSERT,
UPDATE, ou DELETE.
As regras de atualização são aplicadas pelo sistema de regras quando
a relação de resultado e o tipo de comando de uma árvore de consulta
são iguais ao objeto e evento fornecidos no comando
CREATE RULE.
Para regras de atualização, o sistema de regras cria uma lista
de árvores de consulta.
Inicialmente, a lista da árvore de consulta está vazia.
Pode haver zero (palavra-chave NOTHING),
uma ou várias ações.
Para simplificar, vamos ver uma regra com uma ação.
Esta regra pode ter uma qualificação, ou não, e pode ser
INSTEAD, ou ALSO (o padrão).
O que é uma qualificação de regra? É uma restrição que diz quando
as ações da regra devem ser executadas, e quando não.
Esta qualificação só pode referenciar as pseudo-relações
NEW e/ou OLD, que basicamente
representam a relação dada como objeto
(mas com um significado especial).
Portanto, temos três casos que produzem as seguintes árvores de consulta para uma regra de ação única.
ALSO ou
INSTEADa árvore de consulta da ação de regra, com adição da qualificação da árvore de consulta original
ALSOa árvore de consulta da ação da regra, com a adição da qualificação da regra e a qualificação da árvore de consulta original
INSTEADa árvore de consulta da ação de regra, com a qualificação da consulta e a qualificação da árvore de consulta original; e acrescentando a árvore de consulta original com a qualificação inversa da regra
Por fim, se a regra for ALSO, a árvore de
consulta original inalterada será adicionada à lista.
Como apenas as regras INSTEAD qualificadas já
adicionam a árvore de consulta original, termina-se com uma ou duas
árvores de consulta de saída para uma regra com uma ação.
Para regras ON INSERT, a consulta original
(se não for suprimida por INSTEAD) é feita
antes de quaisquer ações adicionadas por regras.
Isto permite que as ações vejam a(s) linha(s) inserida(s).
Mas para as regras ON UPDATE e
ON DELETE, a consulta original é executada após
as ações adicionadas pelas regras.
Isto garante que as ações possam ver as linhas a serem atualizadas
ou excluídas; caso contrário, as ações não podem fazer nada, porque
não encontram nenhuma linha que corresponda às suas qualificações.
As árvores de consulta geradas a partir de ações de regra são lançadas no sistema de reescrita novamente, e talvez sejam aplicadas mais regras, resultando em mais ou menos árvores de consulta. Portanto, as ações de uma regra devem ter um tipo de comando diferente, ou uma relação de resultado diferente da regra em si, caso contrário, este processo recursivo terminará em um ciclo infinito. (A expansão recursiva de uma regra será detectada e relatada como um erro.)
As árvores de consulta encontradas nas ações do catálogo do sistema
pg_rewrite são apenas modelos.
Uma vez que podem referenciar as entradas da tabela de intervalos
para NEW e OLD, algumas
substituições devem ser feitas antes que possam ser usadas.
Para qualquer referência a NEW, a lista de destino
da consulta original é procurada por uma entrada correspondente.
Se encontrada, a expressão dessa entrada substituirá a referência.
Caso contrário, NEW significa o mesmo que
OLD (para o UPDATE), ou é
substituído pelo valor nulo (para o INSERT).
Qualquer referência a OLD é substituída por uma
referência à entrada da tabela de intervalo que é a relação de
resultado.
Após o sistema terminar de aplicar as regras de atualização, serão aplicadas as regras de visão à(s) árvore(s) de consulta produzida(s). As visões não podem inserir novas ações de atualização, portanto, não há necessidade de aplicar regras de atualização à saída da reescrita de visão.
Digamos que queremos rastrear alterações na coluna
cadarço_disp da relação
cadarço_dados.
Então vamos definir uma tabela de registro e uma regra que escreve
condicionalmente uma entrada de registro quando um comando
UPDATE é executado na tabela
cadarço_dados.
CREATE TABLE cadarço_log (
cadarço_nome text, -- cadarço alterado
cadarço_disp integer, -- novo valor disponível
log_quem text, -- quem alterou
log_quando timestamp -- quando alterou
);
CREATE RULE log_cadarço AS ON UPDATE TO cadarço_dados
WHERE NEW.cadarço_disp <> OLD.cadarço_disp
DO INSERT INTO cadarço_log VALUES (
NEW.cadarço_nome,
NEW.cadarço_disp,
current_user,
current_timestamp
);
Agora alguém executa
UPDATE cadarço_dados SET cadarço_disp = 6 WHERE cadarço_nome = 'cad7';
e consultando a tabela de registro encontramos:
SELECT * FROM cadarço_log;
cadarço_nome | cadarço_disp | log_quem | log_quando --------------+--------------+----------+---------------------------- cad7 | 6 | ana | 2026-05-22 15:35:58.615653 (1 linha)
É o que se esperava. O que aconteceu por trás foi o seguinte. O analisador criou a árvore de consulta:
UPDATE cadarço_dados SET cadarço_disp = 6 FROM cadarço_dados cadarço_dados WHERE cadarço_dados.cadarço_nome = 'cad7';
Existe a regra log_cadarço para
ON UPDATE com a expressão de qualificação da regra
NEW.cadarço_disp <> OLD.cadarço_disp
e a ação
INSERT INTO cadarço_log VALUES (
new.cadarço_nome, new.cadarço_disp,
current_user, current_timestamp )
FROM cadarço_dados new, cadarço_dados old;
(Isto parece um pouco estranho, já que normalmente não se pode
escrever INSERT ... VALUES ... FROM.
A cláusula FROM aqui é apenas para indicar que
existem entradas da tabela de intervalos na árvore de consulta para
new e old.
Eles são necessários para poderem ser referenciados por variáveis
na árvore de consulta do comando INSERT.)
A regra é uma regra ALSO qualificada, portanto,
o sistema de regras deve retornar duas árvores de consulta:
a ação da regra modificada, e a árvore de consulta original.
No passo 1, a tabela de intervalos da consulta original é
incorporada à árvore de consulta de ação da regra.
Isto resulta em:
INSERT INTO cadarço_log VALUES (
new.cadarço_nome, new.cadarço_disp,
current_user, current_timestamp )
FROM cadarço_dados new, cadarço_dados old,
cadarço_dados cadarço_dados;
No passo 2, a qualificação da regra é adicionada, então o conjunto
de resultados fica restrito às linhas onde
cadarço_disp muda de valor:
INSERT INTO cadarço_log VALUES (
new.cadarço_nome, new.cadarço_disp,
current_user, current_timestamp )
FROM cadarço_dados new, cadarço_dados old,
cadarço_dados cadarço_dados
WHERE new.cadarço_disp <> old.cadarço_disp;
(Isto parece ainda mais estranho, já que
INSERT ... VALUES também não tem uma cláusula
WHERE, mas o planejador e o executor não terão
dificuldade com isto.
Eles precisam oferecer suporte a esta mesma funcionalidade
de qualquer maneira para INSERT ... SELECT.)
No passo 3, a qualificação da árvore de consulta original é adicionada, restringindo ainda mais o conjunto de resultados apenas às linhas que teriam sido tocadas pela consulta original:
INSERT INTO cadarço_log VALUES (
new.cadarço_nome, new.cadarço_disp,
current_user, current_timestamp )
FROM cadarço_dados new, cadarço_dados old,
cadarço_dados cadarço_dados
WHERE new.cadarço_disp <> old.cadarço_disp
AND cadarço_dados.cadarço_nome = 'cad7';
O passo 4 substitui as referências a NEW pelas
entradas da lista de destino da árvore de consulta original, ou pelas
referências de variáveis correspondentes da relação de resultado:
INSERT INTO cadarço_log VALUES (
cadarço_dados.cadarço_nome, 6,
current_user, current_timestamp )
FROM cadarço_dados new, cadarço_dados old,
cadarço_dados cadarço_dados
WHERE 6 <> old.cadarço_disp
AND cadarço_dados.cadarço_nome = 'cad7';
O passo 5 altera as referências OLD para
referências da relação de resultado:
INSERT INTO cadarço_log VALUES (
cadarço_dados.cadarço_nome, 6,
current_user, current_timestamp )
FROM cadarço_dados new, cadarço_dados old,
cadarço_dados cadarço_dados
WHERE 6 <> cadarço_dados.cadarço_disp
AND cadarço_dados.cadarço_nome = 'cad7';
É isto.
Como a regra é ALSO, também é gerada a árvore
de consulta original.
Resumindo, a saída do sistema de regras é uma lista de duas árvores
de consulta correspondendo a estas declarações:
INSERT INTO cadarço_log VALUES (
cadarço_dados.cadarço_nome, 6,
current_user, current_timestamp )
FROM cadarço_dados
WHERE 6 <> cadarço_dados.cadarço_disp
AND cadarço_dados.cadarço_nome = 'cad7';
UPDATE cadarço_dados SET cadarço_disp = 6
WHERE cadarço_nome = 'cad7';
São executadas nesta ordem, sendo exatamente para isto que a regra foi criada.
As substituições e as qualificações adicionadas garantem que, se a consulta original fosse, digamos:
UPDATE cadarço_dados SET cadarço_cor = 'verde' WHERE cadarço_nome = 'cad7';
nenhuma entrada de registro seria escrita.
Neste caso, a árvore de consulta original não contém uma entrada
de lista de destino para cadarço_disp,
portanto NEW.cadarço_disp será substituído por
cadarço_dados.cadarço_disp.
Assim, o comando extra gerado pela regra é:
INSERT INTO cadarço_log VALUES (
cadarço_dados.cadarço_nome, cadarço_dados.cadarço_disp,
current_user, current_timestamp )
FROM cadarço_dados
WHERE cadarço_dados.cadarço_disp <> cadarço_dados.cadarço_disp
AND cadarço_dados.cadarço_nome = 'cad7';
e esta qualificação nunca será verdade.
Também funcionará se a consulta original modificar várias linhas. Então, se alguém executar o comando:
UPDATE cadarço_dados SET cadarço_disp = 0 WHERE cadarço_cor = 'preto';
quatro linhas são de fato atualizadas (cad1,
cad2, cad3, e
cad4).
Mas cad3 já tem cadarço_disp = 0.
Neste caso, a qualificação das árvores de consulta originais
é diferente, e isto resulta na árvore de consulta extra
INSERT INTO cadarço_log
SELECT cadarço_dados.cadarço_nome, 0,
current_user, current_timestamp
FROM cadarço_dados
WHERE 0 <> cadarço_dados.cadarço_disp
AND cadarço_dados.cadarço_cor = 'preto';
sendo gerada pela regra. Esta árvore de consulta certamente irá inserir três novas entradas de registro. E isto é inteiramente correto.
Aqui podemos ver porque é importante que a árvore de consulta
original seja executada por último.
Se o comando UPDATE tivesse sido executado
primeiro, todas as linhas já teriam sido zeradas, então o
comando INSERT que faz o registro não encontraria
nenhuma linha onde
0 <> cadarço_dados.cadarço_disp.
Uma maneira simples de proteger as relações de visão da
possibilidade mencionada de que alguém possa tentar executar
os comandos INSERT, UPDATE,
ou DELETE, diretamente sobre elas, é deixando
estas árvores de consulta serem jogadas fora.
Assim podem ser criadas as regras:
CREATE RULE sapato_ins_proteção AS ON INSERT TO sapato
DO INSTEAD NOTHING;
CREATE RULE sapato_upd_proteção AS ON UPDATE TO sapato
DO INSTEAD NOTHING;
CREATE RULE sapato_del_proteção AS ON DELETE TO sapato
DO INSTEAD NOTHING;
Se alguém agora tentar fazer qualquer uma dessas operações na
relação da visão sapato, o sistema de regras
aplicará estas regras.
Como as regras não têm ações, e são INSTEAD,
a lista resultante de árvores de consulta ficará vazia, e toda
a consulta se tornará nada, porque não há mais nada para ser
otimizado ou executado após o sistema de regras estar concluído.
Uma maneira mais sofisticada de usar o sistema de regras é criando
regras que reescrevem a árvore de consulta em uma que faça
a operação correta nas tabelas reais.
Para fazer isto na visão cadarço, são criadas
as seguintes regras:
CREATE RULE cadarço_insert AS ON INSERT TO cadarço
DO INSTEAD
INSERT INTO cadarço_dados VALUES (
NEW.cadarço_nome,
NEW.cadarço_disp,
NEW.cadarço_cor,
NEW.cadarço_comp,
NEW.cadarço_unid
);
CREATE RULE cadarço_update AS ON UPDATE TO cadarço
DO INSTEAD
UPDATE cadarço_dados
SET cadarço_nome = NEW.cadarço_nome,
cadarço_disp = NEW.cadarço_disp,
cadarço_cor = NEW.cadarço_cor,
cadarço_comp = NEW.cadarço_comp,
cadarço_unid = NEW.cadarço_unid
WHERE cadarço_nome = OLD.cadarço_nome;
CREATE RULE cadarço_delete AS ON DELETE TO cadarço
DO INSTEAD
DELETE FROM cadarço_dados
WHERE cadarço_nome = OLD.cadarço_nome;
Se for desejado oferecer suporte a consultas com a cláusula
RETURNING na visão, é necessário fazer com que
as regras incluam cláusulas RETURNING que
computam as linhas da visão.
Isto é geralmente bastante trivial para visões em uma única tabela,
mas é um pouco entediante para visões com junção como
cadarço.
Um exemplo para o caso de inserção é:
CREATE RULE cadarço_insert AS ON INSERT TO cadarço
DO INSTEAD
INSERT INTO cadarço_dados VALUES (
NEW.cadarço_nome,
NEW.cadarço_disp,
NEW.cadarço_cor,
NEW.cadarço_comp,
NEW.cadarço_unid
)
RETURNING
cadarço_dados.*,
(SELECT cadarço_dados.cadarço_comp * u.unidade_fator
FROM unidade u WHERE cadarço_dados.cadarço_unid = u.unidade_nome);
Note que esta regra oferece suporte as consultas
INSERT e INSERT RETURNING
na visão — a cláusula RETURNING é
simplesmente ignorada para INSERT.
Note que na cláusula RETURNING de uma regra,
OLD e NEW se referem às
pseudo-relações adicionadas como entradas extras na tabela de
intervalos da consulta reescrita, e não às linhas antigas/novas
na relação de resultado.
Assim, por exemplo, em uma regra que oferece suporte a consultas
UPDATE nesta visão, se a cláusula
RETURNING contivesse
old.cadarço_nome, o nome antigo sempre seria
retornado, independentemente da cláusula
RETURNING na consulta da visão especificar
OLD ou NEW, o que pode ser
confuso.
Para evitar esta confusão e permitir o retorno de valores antigos
e novos em consultas na visão, a cláusula RETURNING
na definição da regra deve se referir a entradas da relação de
resultado como, por exemplo,
cadarço_dados.cadarço_nome,
sem especificar OLD ou NEW.
Agora vamos supor que, ocasionalmente, chegue à loja um pacote
de cadarços, e uma grande lista de peças junto.
Mas não se deseja atualizar manualmente a visão
cadarço todas às vezes.
Em vez disso, são definidas duas pequenas tabelas: uma onde se pode
inserir os itens da lista de peças, e outra com um truque especial.
Os comandos de criação para estas tabelas incluindo a regra são:
CREATE TABLE cadarço_chegada (
chegada_nome text,
chegada_quant integer
);
CREATE TABLE cadarço_ok (
ok_nome text,
ok_quant integer
);
CREATE RULE cadarço_ok_ins AS ON INSERT TO cadarço_ok
DO INSTEAD
UPDATE cadarço
SET cadarço_disp = cadarço_disp + NEW.ok_quant
WHERE cadarço_nome = NEW.ok_nome;
Agora pode-se preencher a tabela cadarço_chegada
com os dados da lista de peças:
SELECT * FROM cadarço_chegada; chegada_nome | chegada_quant --------------+--------------- cad3 | 10 cad6 | 20 cad8 | 20 (3 linhas)
Vamos dar uma olhada rápida nos dados correntes:
SELECT * FROM cadarço ORDER BY cadarço_nome;
cadarço_nome | cadarço_disp | cadarço_cor | cadarço_comp | cadarço_unid | cadarço_comp_cm --------------+--------------+-------------+--------------+--------------+----------------- cad1 | 5 | preto | 80 | cm | 80 cad2 | 6 | preto | 100 | cm | 100 cad3 | 0 | preto | 35 | pol | 88.9 cad4 | 8 | preto | 40 | pol | 101.6 cad5 | 4 | marrom | 1 | m | 100 cad6 | 0 | marrom | 0.9 | m | 90 cad7 | 6 | verde | 60 | cm | 60 cad8 | 1 | marrom | 40 | pol | 101.6 (8 linhas)
Agora vamos adicionar os cadarços chegados com
INSERT INTO cadarço_ok SELECT * FROM cadarço_chegada;
e conferir os resultados:
SELECT * FROM cadarço ORDER BY cadarço_nome;
cadarço_nome | cadarço_disp | cadarço_cor | cadarço_comp | cadarço_unid | cadarço_comp_cm --------------+--------------+-------------+--------------+--------------+----------------- cad1 | 5 | preto | 80 | cm | 80 cad2 | 6 | preto | 100 | cm | 100 cad3 | 10 | preto | 35 | pol | 88.9 cad4 | 8 | preto | 40 | pol | 101.6 cad5 | 4 | marrom | 1 | m | 100 cad6 | 20 | marrom | 0.9 | m | 90 cad7 | 6 | verde | 60 | cm | 60 cad8 | 21 | marrom | 40 | pol | 101.6 (8 linhas)
SELECT * FROM cadarço_log;
cadarço_nome | cadarço_disp | log_quem | log_quando --------------+--------------+----------+---------------------------- cad7 | 6 | ana | 2026-05-22 15:56:59.506778 cad3 | 10 | ana | 2026-05-22 16:00:36.987003 cad6 | 20 | ana | 2026-05-22 16:00:36.987003 cad8 | 21 | ana | 2026-05-22 16:00:36.987003 (4 linhas)
É um longo caminho desde INSERT ... SELECT
até estes resultados.
E a descrição da transformação da árvore de consulta será a última
neste capítulo.
Primeiro, há a saída do analisador:
INSERT INTO cadarço_ok SELECT cadarço_chegada.chegada_nome, cadarço_chegada.chegada_quant FROM cadarço_chegada cadarço_chegada, cadarço_ok cadarço_ok;
Agora a primeira regra cadarço_ok_ins é aplicada,
transformando isto em
UPDATE cadarço
SET cadarço_disp = cadarço.cadarço_disp + cadarço_chegada.chegada_quant
FROM cadarço_chegada cadarço_chegada, cadarço_ok cadarço_ok,
cadarço_ok old, cadarço_ok new,
cadarço cadarço
WHERE cadarço.cadarço_nome = cadarço_chegada.chegada_nome;
jogando fora o comando INSERT original em
cadarço_ok.
Esta consulta reescrita é passada para o sistema de regras novamente,
e a segunda regra aplicada cadarço_update produz:
UPDATE cadarço_dados
SET cadarço_nome = cadarço.cadarço_nome,
cadarço_disp = cadarço.cadarço_disp + cadarço_chegada.chegada_quant,
cadarço_cor = cadarço.cadarço_cor,
cadarço_comp = cadarço.cadarço_comp,
cadarço_unid = cadarço.cadarço_unid
FROM cadarço_chegada cadarço_chegada, cadarço_ok cadarço_ok,
cadarço_ok old, cadarço_ok new,
cadarço cadarço, cadarço old,
cadarço new, cadarço_dados cadarço_dados
WHERE cadarço.cadarço_nome = cadarço_chegada.chegada_nome
AND cadarço_dados.cadarço_nome = cadarço.cadarço_nome;
Novamente, é uma regra INSTEAD e a árvore de
consulta anterior é descartada.
Note que esta consulta ainda utiliza a visão cadarço.
Mas o sistema de regras não termina com esta etapa, então ele
continua e aplica a regra _RETURN, obtendo:
UPDATE cadarço_dados
SET cadarço_nome = s.cadarço_nome,
cadarço_disp = s.cadarço_disp + cadarço_chegada.chegada_quant,
cadarço_cor = s.cadarço_cor,
cadarço_comp = s.cadarço_comp,
cadarço_unid = s.cadarço_unid
FROM cadarço_chegada cadarço_chegada, cadarço_ok cadarço_ok,
cadarço_ok old, cadarço_ok new,
cadarço cadarço, cadarço old,
cadarço new, cadarço_dados cadarço_dados,
cadarço old, cadarço new,
cadarço_dados s, unidade u
WHERE s.cadarço_nome = cadarço_chegada.chegada_nome
AND cadarço_dados.cadarço_nome = s.cadarço_nome;
Por fim, a regra log_cadarço é aplicada,
produzindo a árvore de consulta extra:
INSERT INTO cadarço_log
SELECT s.cadarço_nome,
s.cadarço_disp + cadarço_chegada.chegada_quant,
current_user,
current_timestamp
FROM cadarço_chegada cadarço_chegada, cadarço_ok cadarço_ok,
cadarço_ok old, cadarço_ok new,
cadarço cadarço, cadarço old,
cadarço new, cadarço_dados cadarço_dados,
cadarço old, cadarço new,
cadarço_dados s, unidade u,
cadarço_dados old, cadarço_dados new
cadarço_log cadarço_log
WHERE s.cadarço_nome = cadarço_chegada.chegada_nome
AND cadarço_dados.cadarço_nome = s.cadarço_nome
AND (s.cadarço_disp + cadarço_chegada.chegada_quant) <> s.cadarço_disp;
Depois disso, o sistema de regras fica sem regras, e retorna as árvores de consulta geradas.
Portanto, terminamos com duas árvores de consulta finais que são equivalentes às instruções SQL:
INSERT INTO cadarço_log
SELECT s.cadarço_nome,
s.cadarço_disp + cadarço_chegada.chegada_quant,
current_user,
current_timestamp
FROM cadarço_chegada cadarço_chegada, cadarço_dados cadarço_dados,
cadarço_dados s
WHERE s.cadarço_nome = cadarço_chegada.chegada_nome
AND cadarço_dados.cadarço_nome = s.cadarço_nome
AND s.cadarço_disp + cadarço_chegada.chegada_quant <> s.cadarço_disp;
UPDATE cadarço_dados
SET cadarço_disp = cadarço_dados.cadarço_disp + cadarço_chegada.chegada_quant
FROM cadarço_chegada cadarço_chegada,
cadarço_dados cadarço_dados,
cadarço_dados s
WHERE s.cadarço_nome = cadarço_chegada.cadarço_nome
AND cadarço_dados.cadarço_nome = s.cadarço_nome;
O resultado é que os dados vindos de uma relação inseridos em outra, transformados em atualizações em uma terceira, transformados em atualização em uma quarta, mais o registro dessa atualização final em uma quinta, são reduzidos a duas consultas.
Há um pequeno detalhe que é um pouco feio.
Olhando para as duas consultas, verifica-se que a relação
cadarço_dados aparece duas vezes na tabela
de intervalos, onde definitivamente poderia ser reduzida a uma vez.
O planejador não trata isto, portanto, o plano de execução para
a saída dos sistemas de regras do INSERT será
Nested Loop
-> Merge Join
-> Seq Scan
-> Sort
-> Seq Scan on s
-> Seq Scan
-> Sort
-> Seq Scan on cadarço_chegada
-> Seq Scan on cadarço_dados
enquanto omitindo a entrada da tabela de intervalos extra resultaria em
Merge Join
-> Seq Scan
-> Sort
-> Seq Scan on s
-> Seq Scan
-> Sort
-> Seq Scan on cadarço_chegada
que produz exatamente as mesmas entradas na tabela de registro.
Assim, o sistema de regras gerou uma varredura extra na tabela
cadarço_dados, que absolutamente não é necessária.
E a mesma varredura redundante é feita mais uma vez no
UPDATE.
Mas foi um trabalho muito difícil tornar tudo isto possível.
Agora será feita uma demonstração final do sistema de regras do PostgreSQL e seu poder. Digamos que são adicionados alguns cadarços com cores extraordinárias ao banco de dados (além do verde anterior):
INSERT INTO cadarço VALUES ('cad9', 0, 'rosa', 35.0, 'pol', 0.0);
INSERT INTO cadarço VALUES ('cad10', 1000, 'magenta', 40.0, 'pol', 0.0);
Deseja-se criar uma visão para verificar quais entradas de
cadarço não correspondem a nenhuma cor preferida
de sapato.
A visão para isto é:
CREATE VIEW cadarço_descasado AS
SELECT * FROM cadarço WHERE NOT EXISTS
(SELECT sapato_nome FROM sapato WHERE cadarço_cor_pref = cadarço_cor);
Sua saída é:
SELECT * FROM cadarço_descasado;
cadarço_nome | cadarço_disp | cadarço_cor | cadarço_comp | cadarço_unid | cadarço_comp_cm --------------+--------------+-------------+--------------+--------------+----------------- cad9 | 0 | rosa | 35 | pol | 88.9 cad10 | 1000 | magenta | 40 | pol | 101.6 (2 linhas)
Agora deseja-se configurar para que os cadarços incompatíveis que não estão em estoque sejam excluídos do banco de dados. Para tornar um pouco mais difícil para o PostgreSQL, a exclusão não será feita diretamente. Em vez disso, será criada a visão
CREATE VIEW cadarço_pode_excluir AS
SELECT * FROM cadarço_descasado WHERE cadarço_disp = 0;
executada como
DELETE FROM cadarço WHERE EXISTS
(SELECT * FROM cadarço_pode_excluir
WHERE cadarço_nome = cadarço.cadarço_nome);
resultando em:
CREATE COLLATION "pt-natural" (provider = icu, locale = 'pt-u-kn-true'); SELECT * FROM cadarço ORDER BY cadarço_nome COLLATE "pt-natural";
cadarço_nome | cadarço_disp | cadarço_cor | cadarço_comp | cadarço_unid | cadarço_comp_cm --------------+--------------+-------------+--------------+--------------+----------------- cad1 | 5 | preto | 80 | cm | 80 cad2 | 6 | preto | 100 | cm | 100 cad3 | 10 | preto | 35 | pol | 88.9 cad4 | 8 | preto | 40 | pol | 101.6 cad5 | 4 | marrom | 1 | m | 100 cad6 | 20 | marrom | 0.9 | m | 90 cad7 | 6 | verde | 60 | cm | 60 cad8 | 21 | marrom | 40 | pol | 101.6 cad10 | 1000 | magenta | 40 | pol | 101.6 (9 linhas)
Um comando DELETE em uma visão, com uma
qualificação de subconsulta que no total usa 4 visões
aninhadas/juntadas, onde uma delas possui uma qualificação de
subconsulta contendo uma visão, e onde são usadas colunas de visão
calculadas, é reescrito em uma única árvore de consulta que exclui
os dados solicitados de uma tabela real.
Provavelmente, existem apenas algumas poucas situações no mundo real em que tal construção é necessária. Mas é gratificante saber que funciona.