[firebase-br] Erro na trigger (BI) de uma view - Column does not belong to referenced table.

Márcio Palma mzpalma em gmail.com
Qua Jun 13 12:24:59 -03 2007


Olá pessoal!

Estou com um erros há dias e acredito que seja simples de resolver, mas 
realmente estou "batendo cabeça"... :(

É o seguinte, em alguns lugares tenho um relacionamento 
muitos-para-muitos (aquele que criamos uma tabela que guarda as chaves 
primárias das outras tabelas para fazer o relacionamento).

Na maior aprtes deles, a melhor solução para acesso é criar uma view e 
triggers para atualizar as tabelas, mas está dando um erro muito 
estranho (uso o Firebird 2.01).

Vou colocar abaixo as tabelas:


     * Tabela Compo:


       CREATE TABLE COMPO (
           PK_I_COMPO    INTEGER NOT NULL,
           FK_I_CLIEN    INTEGER,
           S_TRAT        CHAR(5),
           S_NOME        VARCHAR(50) NOT NULL COLLATE WIN_PTBR,
           S_PESSOA      CHAR(1) NOT NULL,
           S_DOC         CHAR(14),
           I_EST_CF      SMALLINT NOT NULL,
           D_NASC        DATE NOT NULL,
           S_CNH_NUM     CHAR(9),
           S_CNH_REG     CHAR(11),
           S_CNH_CLASSE  CHAR(2),
           D_CNH_VENC    DATE,
           D_CNH_1A      DATE,
           S_PROF        VARCHAR(15) COLLATE WIN_PTBR,
           M_OBS         BLOB SUB_TYPE 1 SEGMENT SIZE 80 COLLATE WIN_PTBR
       );


     * Tabela Contt:


       CREATE TABLE CONTT (
           PK_I_CONTT  INTEGER NOT NULL,
           I_TIPO      SMALLINT NOT NULL,
           S_NUM       VARCHAR(50) NOT NULL COLLATE WIN_PTBR
       );


     * Tabela de relacionamento entre as duas acima (ela também tem um 
campo observação):


       CREATE TABLE TR_COM_CTT (
           FK_I_COMPO  INTEGER NOT NULL,
           FK_I_CONTT  INTEGER NOT NULL,
           S_OBS       VARCHAR(10) COLLATE WIN_PTBR
       );


A view é a seguinte:

     * create view VW_CTT_COM(
           PK_I_CONTT,
           FK_I_COMPO,
           I_TIPO,
           S_NUM,
           S_OBS)
       as
       select
           CTT.PK_I_CONTT,
           TR.FK_I_COMPO,
           CTT.I_TIPO, /* de 0 a 3 são telefones, acima é email, etc. */
           CTT.S_NUM,
           TR.S_OBS
       from TR_COM_CTT TR
       join CONTT CTT on CTT.PK_I_CONTT = TR.FK_I_CONTT;


Até aqui tudo bem, nada com erros e tudo legal. O erro que é gerado é 
que me intriga (na listagem logo abaixo), vejam:


/*******************************************************************************
The next statement causes the following error:

Column does not belong to referenced table.
Dynamic SQL Error.
SQL error code = -206.
Column unknown.
OLD.I_TIPO.
At line 18, column 19.
*******************************************************************************/

Não há qualquer lógica em não existir o OLD.I_TIPO pois ele é criado 
automáticamente pelo Firebird dentro de uma trigger e representa o valor 
antes da edição do registro, assim como o NEW representa o valor novo 
(desculpe-me - estou falando coisas básicas - como não sei que BD você 
usa e a sintaxe pode ser diferente, estou passando detalhes do Firebird).

Tentei excluir OLD.I_TIPO (apenas para teste), mas depois ele continua 
informando que as outras colunas NEW.I_TIPO, OLD.S_NUM, NEW.S_NUM, etc 
também não existem...

A trigger é a seguinte:



       create trigger VW_CTT_COM_BI for VW_CTT_COM
       active before insert position 0
       as
       declare variable I_COD_CTT integer; /* PK da tabela CONTT */
       begin

       /******** 1ª parte - tabela de contatos */

        if (new.I_TIPO <= 3) then /* verifica se é um telefone */
           begin /* apenas os 14 primeiros são significativos */
            select PK_I_CONTT /* verifica se o nº já foi cadastrado */
              from CONTT
             where S_NUM starting with substring(new.S_NUM from 1 for 14)
              into :I_COD_CTT;

            if (I_COD_CTT > 0) then /* se i_cod_ctt > 0 então já foi */
               begin /* verifica se é necessário atualizar */



/**************** o erro começa na próxima linha (if) *************/



                if ((old.I_TIPO <> new.I_TIPO)
                   or (old.S_NUM <> new.S_NUM)) then
                   update CONTT
                      set I_TIPO = new.I_TIPO,
                          S_NUM  = new.S_NUM
                    where PK_I_CONTT = :I_COD_CTT;
               end
            else
               begin
                I_COD_CTT = gen_id(GEN_CONTT_ID, 1); /* nova pk */
                insert into CONTT(PK_I_CONTT, I_TIPO, S_NUM)
                     values (I_COD_CTT, new.I_TIPO, new.S_NUM);
               end
           end
        else
           begin /* todos os dígitos são significativos */
            select PK_I_CONTT /* o nº já foi cadastrado? */
              from CONTT
             where S_NUM = new.S_NUM
              into :I_COD_CTT;

            if (I_COD_CTT > 0) then /* se i_cod_ctt > 0 então já foi */
               begin
                if (new.I_TIPO <> old.I_TIPO) then
                   update CONTT /* atualiza apenas se mudou o tipo */
                      set I_TIPO = new.I_TIPO
                    where PK_I_CONTT = :I_COD_CTT;
               end
            else
               begin   /* novo registro */
                I_COD_CTT = gen_id(GEN_CONTT_ID, 1); /* nova pk */
                insert into CONTT(PK_I_CONTT, I_TIPO, S_NUM)
                     values (I_COD_CTT, new.I_TIPO, new.S_NUM);
               end
           end

         /******** 2ª parte - Tabela de Relacionamento */

         if (exists(select *
                    from TR_COM_CTT
                    where (FK_I_CONTT = :I_COD_CTT) and
                          (FK_I_COMPO = new.FK_I_COMPO))) then
            begin /* já existe o relacionamento */
             if (new.S_OBS <> old.S_OBS) then
                update TR_COM_CTT
                   set S_OBS = new.S_OBS
                 where (FK_I_CONTT = :I_COD_CTT) and
                       (FK_I_COMPO = new.FK_I_COMPO);
            end
         else /* o registro na TR não existe ainda */
            insert into TR_COM_CTT(FK_I_COMPO, FK_I_CONTT, S_OBS)
                 values (new.FK_I_COMPO, :I_COD_CTT, new.S_OBS);
       end



Alguém ai já teve algum problema assim? Não consigo ver onde estou 
errando....

Muito obrigado!
Abraços para todos!!

Márcio Palma





Mais detalhes sobre a lista de discussão lista