Re: [pgbr-geral] Trigger mirabolante com View: de Oracle para Postgres
2008/9/18 Mozart Hasse [EMAIL PROTECTED] -- Original Message -- From: William Leite Araújo [EMAIL PROTECTED] 2008/9/17 Mozart Hasse [EMAIL PROTECTED] (...) Atribuir o NEW nas triggers de BEFORE até que aparentemente funcionou, porém tive de deixar todas as triggers como AFTER para resolver outros problemas... Bom, novamente vou alertar que NUNCA, no postgresql, atribuir valores ao registro NEW ou OLD num gatilho AFTER funcionará. A idéia do AFTER é fazer alterações em outras tabelas, e não na que gerou o evento. Sim, eu sei, troquei as atribuições por UPDATES diretos na tabela ao passar para triggers AFTER. Bom, a coisa até que andou, não tenho mais aquele erro do record 'new' is not assigned yet, só que agora resta descobrir como se implementa em Postgres a funcionalidade da qual as triggers originais dependiam: identificar se a chamada atual da trigger function foi disparada de um UPDATE/INSERT/DELETE da aplicação ou da própria trigger... Tive problemas com isso uma vez, e acho que uma possivel solução seria marcar isso numa tabela temporária pela regra da VIEW. É possível executar mais de uma ação na regra. Por exemplo: CREATE RULE regra_do_cao ON INSERT TO [nome da view] DO INSTEAD *(* INSERT INTO [tabela temporaria de marcação] VALUES (...); INSERT INTO [tabela real] VALUES (...) *);* O problema é que eu tenho de marcar a tabela temporária de _dentro_ da trigger... Explicando melhor: eu preciso fazer, por conta do mesmo comando de origem, duas coisas: * ajustar ponteiros dos registros anterior, atual e posterior. A trigger function pode alterar registros (incluindo o registro original) por conta da operação original, e essas alterações não devem disparar novamente a trigger (ou pelo menos devem notar que é uma chamada recursiva e sair sem fazer nada); Nesse sentido, existe a possibilidade de desabilitar o trigger durante a execução do mesmo (caso o usuário tenha essa permissão ou o trigger seja SECURITY DEFINNER). Tipo : ALTER TABLE [tabela] DISABLE TRIGGER xxx; (... comandos pra fazer as alterações ...) ALTER TABLE [tabela] ENABLE TRIGGER xxx; Não sei dizer se desabilitará para todas as transações (acredito que não) ou somente para a corrente. * depois de garantir que os ponteiros estão em ordem, eu tenho de disparar uma function (recálculo de registros posteriores) uma única vez a cada comando 'externo' à trigger, e isso só pode acontecer _depois_ de atualizar o registro original. Esta function pode incluir, alterar e excluir registros por conta da operação original. Essas operações não devem disparar novamente a própria function. Bom, essa function (por ser apenas uma) pode então iniciar seu processamento marcando em uma tabela temporária que está em execução para evitar que ela seja novamente executada, certo? O desejável seria que as atualizações da function de recálculo se aproveitassem da parte de atualização de ponteiros das trigger functions, pois há diversos pontos de atualização e a função depende da integridade dos ponteiros após cada operação. A replicação dessa regra em cada um dos lugares em que a tabela é atualizada tornaria o código horrivelmente complicado, absurdamente redundante e radicalmente difícil de manter. Concordo. Que coisa mais louca... Eu atualizo a tabela de marcação em Oracle na primeira atualização proveniente de qualquer trigger, a fim de saber que as chamadas subsequentes devem ser ignoradas ou devem fazer apenas as operações que não causam recursão. E isso não funciona com o Postgresql, numa tabela temporária? O nome da tabela temporária pode conter, por exemplo, o ID da transação !? Se eu entrar na trigger com a tabela já marcada (conforme sua sugestão), não vou saber quando posso e quando não posso atualizar os registros anteriores e posteriores ou disparar a rotina de recálculo. Se eu puser a chamada dessa rotina de recálculo como comando posterior à atualização do registro na declaração da RULE, ainda assim terei problemas com a recursividade, pois os comandos da trigger e da function de recálculo vão disparar as triggers eternamente. Bom, eu poderia tentar tirar tudo das triggers e fazer rules que chamam um monte de functions numa certa sequência, o que teoricamente acabaria com o problema da recursividade. A questão é... não tem um jeito mais simples ?! Acho que não resolveria o problema. Apenas mudaria o ponto onde ele ocorreria... -- William Leite Araújo Analista de Banco de Dados - QualiConsult ___ pgbr-geral mailing list pgbr-geral@listas.postgresql.org.br https://listas.postgresql.org.br/cgi-bin/mailman/listinfo/pgbr-geral
Re: [pgbr-geral] Trigger mirabolante com View: de Oracle para Postgres
Em 18/09/08, Mozart Hasse[EMAIL PROTECTED] escreveu: -- Original Message -- From: William Leite Araújo[EMAIL PROTECTED] 2008/9/17 Mozart Hasse [EMAIL PROTECTED] (...) Atribuir o NEW nas triggers de BEFORE até que aparentemente funcionou, porém tive de deixar todas as triggers como AFTER para resolver outros problemas... Bom, novamente vou alertar que NUNCA, no postgresql, atribuir valores ao registro NEW ou OLD num gatilho AFTER funcionará. A idéia do AFTER é fazer alterações em outras tabelas, e não na que gerou o evento. Sim, eu sei, troquei as atribuições por UPDATES diretos na tabela ao passar para triggers AFTER. Bom, a coisa até que andou, não tenho mais aquele erro do record 'new' is not assigned yet, só que agora resta descobrir como se implementa em Postgres a funcionalidade da qual as triggers originais dependiam: identificar se a chamada atual da trigger function foi disparada de um UPDATE/INSERT/DELETE da aplicação ou da própria trigger... Tive problemas com isso uma vez, e acho que uma possivel solução seria marcar isso numa tabela temporária pela regra da VIEW. É possível executar mais de uma ação na regra. Por exemplo: CREATE RULE regra_do_cao ON INSERT TO [nome da view] DO INSTEAD *(* INSERT INTO [tabela temporaria de marcação] VALUES (...); INSERT INTO [tabela real] VALUES (...) *);* O problema é que eu tenho de marcar a tabela temporária de _dentro_ da trigger... Explicando melhor: eu preciso fazer, por conta do mesmo comando de origem, duas coisas: * ajustar ponteiros dos registros anterior, atual e posterior. A trigger function pode alterar registros (incluindo o registro original) por conta da operação original, e essas alterações não devem disparar novamente a trigger (ou pelo menos devem notar que é uma chamada recursiva e sair sem fazer nada); * depois de garantir que os ponteiros estão em ordem, eu tenho de disparar uma function (recálculo de registros posteriores) uma única vez a cada comando 'externo' à trigger, e isso só pode acontecer _depois_ de atualizar o registro original. Esta function pode incluir, alterar e excluir registros por conta da operação original. Essas operações não devem disparar novamente a própria function. Veja a solução proposta pelo Pavel Stehule para evitar chamadas recursivas: http://www.nabble.com/Synchronize-two-similar-tables%3A-recursive-triggers-to19545281.html O desejável seria que as atualizações da function de recálculo se aproveitassem da parte de atualização de ponteiros das trigger functions, pois há diversos pontos de atualização e a função depende da integridade dos ponteiros após cada operação. A replicação dessa regra em cada um dos lugares em que a tabela é atualizada tornaria o código horrivelmente complicado, absurdamente redundante e radicalmente difícil de manter. Eu atualizo a tabela de marcação em Oracle na primeira atualização proveniente de qualquer trigger, a fim de saber que as chamadas subsequentes devem ser ignoradas ou devem fazer apenas as operações que não causam recursão. Se eu entrar na trigger com a tabela já marcada (conforme sua sugestão), não vou saber quando posso e quando não posso atualizar os registros anteriores e posteriores ou disparar a rotina de recálculo. Se eu puser a chamada dessa rotina de recálculo como comando posterior à atualização do registro na declaração da RULE, ainda assim terei problemas com a recursividade, pois os comandos da trigger e da function de recálculo vão disparar as triggers eternamente. Bom, eu poderia tentar tirar tudo das triggers e fazer rules que chamam um monte de functions numa certa sequência, o que teoricamente acabaria com o problema da recursividade. A questão é... não tem um jeito mais simples ?! Osvaldo ___ pgbr-geral mailing list pgbr-geral@listas.postgresql.org.br https://listas.postgresql.org.br/cgi-bin/mailman/listinfo/pgbr-geral
Re: [pgbr-geral] Trigger mirabolante com View: de Oracle para Postgres
2008/9/15 Mozart Hasse [EMAIL PROTECTED] 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 Não há, no postgresql, trigger sobre a view. Use CREATE RULE. É até melhor, porque uma regra pode ser aplicada a um SELECT também. 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 pgbr-geral@listas.postgresql.org.br https://listas.postgresql.org.br/cgi-bin/mailman/listinfo/pgbr-geral -- William Leite Araújo Analista de Banco de Dados - QualiConsult ___ pgbr-geral mailing list pgbr-geral@listas.postgresql.org.br https://listas.postgresql.org.br/cgi-bin/mailman/listinfo/pgbr-geral
Re: [pgbr-geral] Trigger mirabolante com View: de Oracle para Postgres
Mozart Hasse escreveu: 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. pq vc não faz uma trigger *Before Insert* e muda o valor antes dele ser gravado? assim new.nomedocampo = (SELECT blablabla); e outra trigger no after delete para atualizar (um laço) os registros afetados (acredito que sejam todos os posteriores) -- Esta mensagem foi verificada pelo sistema de Anti-virus da SJB Solados. ___ pgbr-geral mailing list pgbr-geral@listas.postgresql.org.br https://listas.postgresql.org.br/cgi-bin/mailman/listinfo/pgbr-geral
Re: [pgbr-geral] Trigger mirabolante com View: de Oracle para Postgres
Emerson, Mozart Hasse escreveu: 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. pq vc não faz uma trigger *Before Insert* e muda o valor antes dele ser gravado? assim new.nomedocampo = (SELECT blablabla); e outra trigger no after delete para atualizar (um laço) os registros afetados (acredito que sejam todos os posteriores) O problema é que eu teria de aplicar uma regra de negócio complicadíssima sobre o registro inserido/alterado (adaptando umas 500 linhas de querys para consultar os outros registros incluindo o NEW) e manter essa mesmíssima regra duplicada em outro trecho que atualiza os registros posteriores ao que foi atualizado (independente do NEW/OLD). Corro ainda o risco de precisar triplicar essa regra ao fazer uma trigger específica para o UPDATE e outra para o DELETE. Eu já tenho um roteiro de testes bastante extenso para validar isso considerando que a regra de negócio está em um lugar só, e se eu precisar duplicar o código vou tornar meu processo de homologação ainda mais complexo, além de piorar *muito* a minha manutenção daqui por diante. Posso tentar fazer isso pelo ganho esperado em desempenho e redução no tráfego de rede, mas vai ser bem difícil vender essa idéia (duplicação de regra de negócio) devido ao custo de manutenção posterior, pois vai exatamente e radicalmente contra todos os nossos esforços. Agradeço a sugestão, em último caso vou segui-la, porém ainda estou à procura de uma opção que não dê ao Postgres um diferencial tão negativo frente ao SQL Server/Oracle. Atenciosamente, Mozart Hasse ___ pgbr-geral mailing list pgbr-geral@listas.postgresql.org.br https://listas.postgresql.org.br/cgi-bin/mailman/listinfo/pgbr-geral
Re: [pgbr-geral] Trigger mirabolante com View: de Oracle para Postgres
Criando regras de INSERT e UPDATE funciona? 2008/9/16 Mozart Hasse [EMAIL PROTECTED] Emerson, Mozart Hasse escreveu: 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. pq vc não faz uma trigger *Before Insert* e muda o valor antes dele ser gravado? assim new.nomedocampo = (SELECT blablabla); e outra trigger no after delete para atualizar (um laço) os registros afetados (acredito que sejam todos os posteriores) O problema é que eu teria de aplicar uma regra de negócio complicadíssima sobre o registro inserido/alterado (adaptando umas 500 linhas de querys para consultar os outros registros incluindo o NEW) e manter essa mesmíssima regra duplicada em outro trecho que atualiza os registros posteriores ao que foi atualizado (independente do NEW/OLD). Corro ainda o risco de precisar triplicar essa regra ao fazer uma trigger específica para o UPDATE e outra para o DELETE. Eu já tenho um roteiro de testes bastante extenso para validar isso considerando que a regra de negócio está em um lugar só, e se eu precisar duplicar o código vou tornar meu processo de homologação ainda mais complexo, além de piorar *muito* a minha manutenção daqui por diante. Posso tentar fazer isso pelo ganho esperado em desempenho e redução no tráfego de rede, mas vai ser bem difícil vender essa idéia (duplicação de regra de negócio) devido ao custo de manutenção posterior, pois vai exatamente e radicalmente contra todos os nossos esforços. Agradeço a sugestão, em último caso vou segui-la, porém ainda estou à procura de uma opção que não dê ao Postgres um diferencial tão negativo frente ao SQL Server/Oracle. Atenciosamente, Mozart Hasse ___ pgbr-geral mailing list pgbr-geral@listas.postgresql.org.br https://listas.postgresql.org.br/cgi-bin/mailman/listinfo/pgbr-geral -- William Leite Araújo Analista de Banco de Dados - QualiConsult ___ pgbr-geral mailing list pgbr-geral@listas.postgresql.org.br https://listas.postgresql.org.br/cgi-bin/mailman/listinfo/pgbr-geral
Re: [pgbr-geral] Trigger mirabolante com View: de Oracle para Postgres
Olá William, From: William Leite Araújo [EMAIL PROTECTED] Subject: Re: [pgbr-geral] Trigger mirabolante com View: de Oracle para Postgres Não há, no postgresql, trigger sobre a view. Use CREATE RULE. É até melhor, porque uma regra pode ser aplicada a um SELECT também. Eu cogitei essa opção, porém não sei se ela pode ser usada no meu caso específico: http://www.postgresql.org/docs/8.3/static/rules-triggers.html If checks for valid values are required, and in the case of an invalid value an error message should be generated, it must be done by a trigger. O problema é que no meio das minhas triggers eu *tenho* validações que podem gerar mensagens de erro, logo não sei se essa opção seria viável no meu caso. Outro inconveniente é que rules se aplicam sobre comandos inteiros, não sobre atualizações registro a registro. Mudar a lógica da trigger/stored procedure para trabalhar sobre o comando ao invés de trabalhar sobre registros da tabela seria uma mudança extremamente radical, cujas implicações no desempenho me preocupam bastante. Vou ler a documentação e fazer alguns testes. Obrigado pela sugestão. Mozart Hasse ___ pgbr-geral mailing list pgbr-geral@listas.postgresql.org.br https://listas.postgresql.org.br/cgi-bin/mailman/listinfo/pgbr-geral
Re: [pgbr-geral] Trigger mirabolante com View: de Oracle para Postgres
2008/9/16 Mozart Hasse [EMAIL PROTECTED] Olá William, (...) Eu cogitei essa opção, porém não sei se ela pode ser usada no meu caso específico: http://www.postgresql.org/docs/8.3/static/rules-triggers.html If checks for valid values are required, and in the case of an invalid value an error message should be generated, it must be done by a trigger. O problema é que no meio das minhas triggers eu *tenho* validações que podem gerar mensagens de erro, logo não sei se essa opção seria viável no meu caso. Bom, quando eu usei rules em views que eram simplesmente copias da tabela original, as mesmas eram : CREATE RULE [nome] AS ON INSERT TO [nome view] DO INSTEAD INSERT INTO [tabela original](COALESCE(new.[campo1], DEFAULT),COALESCE(new.[campo2],DEFAULT),...); E funcionavam certinho. Item para ocaso do update. Havia a facilidade de um ID de registro nunca poder ser alterado. Assim ... DO INSTEAD UPDATE [tabela original] SET [campo1] = new.[campo1] ... WHERE ID = new.[ID] sempre funcionava. Na verdade, obviamente, eu tinha funções para criar as regras... Outro inconveniente é que rules se aplicam sobre comandos inteiros, não sobre atualizações registro a registro. Mudar a lógica da trigger/stored procedure para trabalhar sobre o comando ao invés de trabalhar sobre registros da tabela seria uma mudança extremamente radical, cujas implicações no desempenho me preocupam bastante. Bom, acho que o dito acima contesta essa afirmação. Não precisa alterar seus triggers, desde que estejam na tabela original... -- William Leite Araújo Analista de Banco de Dados - QualiConsult ___ pgbr-geral mailing list pgbr-geral@listas.postgresql.org.br https://listas.postgresql.org.br/cgi-bin/mailman/listinfo/pgbr-geral
[pgbr-geral] Trigger mirabolante com View: de Oracle para Postgres
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 pgbr-geral@listas.postgresql.org.br https://listas.postgresql.org.br/cgi-bin/mailman/listinfo/pgbr-geral