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
