impedir que o clientdataset verifique violacao de chave prim

25/11/2005

2

Estou passando pelo seguinte problema: tenho no meu banco de dados interbase uma trigger que vai gerar um número único pro meu codprod caso este seja 0 ou null.

Se o codprod for <> de 0 ou null, significa que não é novo, mas sim um registro que já foi inserido em um outro banco que eu estou copiando. Tenho certeza que é unico.

estou com uma tabela em dbf pra converter pro interbase. tenho que ler os registros dali e copiar pro outro banco, de modo que a trigger gere sozinha. o problema é que se eu não colocar nada no codprod, ele dá o erro: ´codprod must have a value´. E se eu coloco zero em todos, pior, ele dá key violation. não queria dar um commit a cada iteração do meu programa. tem como desabilitar a checagem do clientdataset?


Responder

Posts

há pelo menos duas formas de resolver esse problema:

- tire o IF da trigger e continue passando 0 para todos os registros ou
- se o campo for persistente no clientdataset, altere a propriedade Required para false.


Responder

25/11/2005

Vitor Rubio

- se o campo for persistente no clientdataset, altere a propriedade Required para false.


o campo não eh persistente, pelo contrario, para funcionar com qualquer tabela eu uso o fieldbyname e não ponho nenhum campo persistente no meu client.

já tentei colocar fieldbyname(campo).required := false mas não funcionou.

se eu tirar o if da trigger, ela vai gerar os valores sozinha na ordem dela, mas mesmo assim eu terei que colocar valores diferentes pra chave primaria, pois se eu colocar 0 em todos vai dar key violation.


Responder
para resolver isso a única coisa que eu faço é tirar o IF da trigger.

por padrão as triggers são mais ou menos assim:
CREATE TRIGGER VENDAS_BI FOR VENDAS
ACTIVE BEFORE INSERT POSITION 0
AS
BEGIN
  IF (NEW.ID_VENDA IS NULL) THEN
    NEW.ID_VENDA = GEN_ID(GEN_VENDAS_ID,1);
END

assim é possível gerar o [i:ca3b3e90bb]Key violation[/i:ca3b3e90bb] pois, se você puser um valor no campo, a trigger não irá gerar um novo valor (por conta do IF).

eu tiro a linha do IF:
CREATE TRIGGER VENDAS_BI FOR VENDAS
ACTIVE BEFORE INSERT POSITION 0
AS
BEGIN
    NEW.ID_VENDA = GEN_ID(GEN_VENDAS_ID,1);
END

nesse caso não deveria dar Key violation pois, independente de você enviar um valor para o campo, a trigger será executada e irá gerar um novo valor.

isso também depende muito da sua rotina. se você puder publicá-la...


Responder

25/11/2005

Vitor Rubio

a minha trigger não eh igual essas triggers pra gerar campo de autonumeração normais, ela á um pokinho diferente:

CREATE TRIGGER VENDAS_BI FOR VENDAS 
ACTIVE BEFORE INSERT POSITION 0 
AS 
BEGIN 
  IF ((NEW.ID_VENDA IS NULL) or ([b]NEW.ID_VENDA = 0[/b]))  THEN 
    NEW.ID_VENDA = GEN_ID(GEN_VENDAS_ID,1); 
END


ou seja, se eu passar n chaves primarias com valor 0, era pra entrar dentro do if e gerar o código. o problema é que o clientdataset tá querendo validar a chave, então na inclusão do segundo registro, como a chave tambem é 0, ele dá key violation. a exception ocorre logo no post, e não no applyupdates.


Responder
entendi.
de qualquer forma eu sugiro que você retire esse IF (pra mim, ele não faz o menor sentido, a menos que em algum momento você deseje ignorá-la, passando um valor para o campo).
aí, no seu caso, seria mais fácil criar uma variável numérica para ser usada como ID e incrementá-la a cada inserção de registro.
quando for executado o ApplyUpdates o banco se encarregará de colocar os valores corretos.


Responder

28/11/2005

Vitor Rubio

era isso o que eu faria se a minha trigger estivesse sem o if.

O objetivi da minha trigger eh esse mesmo, quando eu passo um valor ele ignora a trigger e grava o valor que eu colocar.

é garantido que esse valor é unico por causa de um sistema de replicação que nós desenvolvemos, onde, não importa em que réplica do banco, o código de cada chave primaria de cada tabela é sempre único nos vários bancos, e quando já existe um registro em um banco que não existe no outro ele é automaticamente copiado pro outro mantendo-se o mesmo código na chave primaria, assim mantem-se a integridade.

Eu consegui resolver o problema da seguinte forma: tirei a chave primaria da minha instrução select do meu ibdataset. Quando agente faz isso, o clientdataset não exige que a chave seja obrigatória nem que seja única. eu posso não passar valor nenhum pra trigger e ela se encarrega de fazer os valores pra mim. como são registros novos que não existem em nenhum banco, a trigger pode se responsabilizar por fazer tudo sozinha.


Responder