[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