Olá,

Estou tentando converter um conjunto de triggers/stored procedures de Oracle 9
para Postgres 8.3.
Julgo ser necessário dar uma visão geral para dar idéia do tamanho da
encrenca:

A trigger tem a intenção de atualizar os valores de alguns campos (saldo
anterior e data inicial do próximo registro) no registro recém incluído, de
forma a deixar o registro incluído com valores coerentes com os registros
anteriores e posteriores, segundo um determinado critério de ordenação.
Visando proteger a integridade da tabela, é importantíssimo que os usuários
e a aplicação não consigam atualizar dados diretamente na tabela sem passar
pela trigger. Aliás, acho que o usuário/desenvolvedor ficará ainda mais
feliz se nem souber que existe uma trigger que corrige os valores para ele.

Devido à natureza recursiva dessa modelagem (eu preciso alterar dados do
próprio registro e em alguns casos dar mais de um UPDATE sobre o mesmo
registro), o Oracle não me permitia alterar o registro diretamente de dentro
da trigger. A solução adotada em Oracle foi a seguinte:

* Mover a tabela original para outro schema e protegê-la contra alterações
feitas diretamente pelos usuários ou pela aplicação;
* Criar uma view com o nome da tabela original;
* criar triggers do tipo INSTEAD OF UPDATE or INSERT or DELETE na View;
* dar os UPDATEs na tabela de fato ou na view, usando para isso SELECTs na
view quando necessário.

A solução, apesar de complexa, resolveu o problema em Oracle com ótimo
desempenho. Eu tenho uma versão igualmente eficiente para SQL Server, só que
preferi não usá-la como referência porque o SQL Server não se importa em
fazer alterações repetidas e recursivas sobre o mesmo registro. 

Falta fazer o mesmo em Postgres...

O problema é que eu não consigo achar meios de implementar a mesma
funcionalidade:

* se eu tento criar triggers com comandos UPDATE/DELETE diretamente sobre a
tabela, o Postgres dá aquele erro infame: 'ERROR: record "new" is not
assigned yet'. Suponho que o problema seja similar ao do Oracle. Estou certo?

* se eu tento usar a mesma solução adotada no Oracle, não consigo criar a
trigger sobre a view. Exemplo:

-- tabela original movida para outro schema
CREATE TABLE gestao.mvtoestq (.../* mais de 50 campos */ );

-- view que eu gostaria de atualizar pela aplicação
create or replace view public.mvtoestq as SELECT * FROM gestao.mvtoestq;

-- trigger function mirabolante que atualiza a view ou a tabela conforme uma
regra de negócio esdrúxula
create or replace FUNCTION finMvtoEstq() returns trigger as 
/* 250 linhas de código que chamam uma SP com mais 800 linhas cheias de
SELECTs monstruosos e UPDATEs mirabolantes */ 
... 
UPDATE public.mvtoestq SET...
...
UPDATE gestao.mvtoestq SET...
...
;

-- trigger sobre a view
CREATE TRIGGER tr_mvtoestq_ins
  instead of INSERT
  ON public.mvtoestq
  FOR EACH ROW
  EXECUTE PROCEDURE finmvtoestq();

Neste último comando o Postgres me retorna:

ERROR:  syntax error at or near "instead"
LINE 2:   instead of INSERT


Finalmente as perguntas: 
1. O que eu faço agora? 
2. Tem como contornar o problema sem precisar de uma View ? 
3. Tem algum jeito de implementar de maneira equivalente ao Oracle ? 
4. Tem algum outro jeito que funcione em Postgres ?
5. Alguém já passou por algo parecido ? Qual a solução adotada ?

Atualmente todos os comandos das triggers e stored procedures estão embutidos
no código da aplicação e são ativados somente quando ela usa Postgres.
Isso complica imensamente a manutenção, dificulta a depuração e aumenta
muito a chance de erros, além de dar ao usuário e ao desenvolvedor a chance
(raramente desperdiçada) de deixar a tabela com dados inconsistentes.

Grato pela atenção,


Mozart Hasse


_______________________________________________
pgbr-geral mailing list
[email protected]
https://listas.postgresql.org.br/cgi-bin/mailman/listinfo/pgbr-geral

Responder a