Como não duplicar dados - firebird
21/06/2023
0
Galera, talvez já tenha uma solução pronta, mas não estou conseguindo achar.
Seguinte, tenho uma tabela de horários programados para determinado carro sair, mais ou menos assim.
1) Minha chave primária é a |dataprevista | horaprevista | Local|
2) Os valores para o Status é "S"-Sim saiu "C"-Cancelado "F"-Finalizado
3) O mesmo carro pode fazer 2 horários diferentes desde que o primeiro esteja com status "F" ou "C"
4) O mesmo carro NÃO pode sair ao mesmo tempo, ou seja, sair 04:59 para o horário previsto 05:00 e 05:10
Aqui é onde eu quero chegar.
NÃO POSSO deixar que o mesmo carro saia no mesmo dia e na mesma hora, no exemplo acima, não posso deixar o mesmo carro, sair as 04:59 no horário de 05:10 pois o mesmo já foi lançado na hora prevista de 05:00.
Não era pra acontecer isso naturalmente, mas tenho 2 usuários fazendo lançamento simultâneos, e pode acontecer deles lançarem o mesmo carro ao mesmo tempo. Gostaria se isso acontecesse, o banco de dados abortar a gravação dos registros.
Não sei se fui claro nos detalhes, mas queria fazer um Unique no Firebird com estas informações.
Desde já agradeço.
Seguinte, tenho uma tabela de horários programados para determinado carro sair, mais ou menos assim.
DataPrevista|HoraPrevista|carro|local|horasaida|status| 05/06/2023 | 05:00 | 0001 | 001 | 04:59 | S | 05/06/2023 | 05:10 | | 002 | | A | 05/06/2023 | 05:20 | | 020 | | A |
1) Minha chave primária é a |dataprevista | horaprevista | Local|
2) Os valores para o Status é "S"-Sim saiu "C"-Cancelado "F"-Finalizado
3) O mesmo carro pode fazer 2 horários diferentes desde que o primeiro esteja com status "F" ou "C"
4) O mesmo carro NÃO pode sair ao mesmo tempo, ou seja, sair 04:59 para o horário previsto 05:00 e 05:10
Aqui é onde eu quero chegar.
NÃO POSSO deixar que o mesmo carro saia no mesmo dia e na mesma hora, no exemplo acima, não posso deixar o mesmo carro, sair as 04:59 no horário de 05:10 pois o mesmo já foi lançado na hora prevista de 05:00.
Não era pra acontecer isso naturalmente, mas tenho 2 usuários fazendo lançamento simultâneos, e pode acontecer deles lançarem o mesmo carro ao mesmo tempo. Gostaria se isso acontecesse, o banco de dados abortar a gravação dos registros.
Não sei se fui claro nos detalhes, mas queria fazer um Unique no Firebird com estas informações.
Desde já agradeço.
Dirceu Morais
Curtir tópico
+ 0
Responder
Posts
21/06/2023
Arthur Heinrich
Você foi bastante claro.
Para não complicar a sua vida, você pode trabalhar com 2 tabelas: carros e horarios
A tabela "carros" deve ter um status para informar se está disponível 'D' ou em atividade 'A', por exemplo.
Ao fazer o update:
O seu banco pode utilizar uma trigger de update para atualizar o status do seu carro.
Vou mostrar um exemplo de trigger em Oracle, mas o mesmo princípio vale para outros bancos:
A primeira parte da trigger checa se a alteração de status é válida (A->S; A->C; S->F). Se não for, aborta o update com uma exception.
Em seguida, tentará alterar o status do carro para 'A' (em atividade). Como ele busca o carro tanto pela chave como pelo status = 'D' (disponível), se não existir um carro com o código informado ou se o status não for disponível, nenhum registro será atualizado.
Caso o número de linhas atualizadas seja zero, a trigger executará uma exception, abortando o update com uma exception.
A exception pode ser tratada pela aplicação. O código e mensagem de erro são retornados para a aplicação, para que a exception possa ser tratada corretamente.
Para outros tipos de banco, a sintaxe utilizada varia, bem como a forma de gerar a exception.
Para não complicar a sua vida, você pode trabalhar com 2 tabelas: carros e horarios
A tabela "carros" deve ter um status para informar se está disponível 'D' ou em atividade 'A', por exemplo.
Ao fazer o update:
update horarios set carro = '0001' and horasaida = '04:59' and status = 'S' where DataPrevista = '05/06/2023' and HoraPrevista = '05:00' and local = '001';
O seu banco pode utilizar uma trigger de update para atualizar o status do seu carro.
Vou mostrar um exemplo de trigger em Oracle, mas o mesmo princípio vale para outros bancos:
create or replace trigger tr_horários_bu before update on horarios referencing new as new old as old for each row begin -- Checagem de erros if (:new.status = 'S' and :old.status <> 'A') then raise_application_error(-20001,'Horário não disponível'); else if (:new.status = 'C' and :old.status <> 'A') then raise_application_error(-20002,'Horário não pode ser cancelado'); else if (:new.status = 'F' and :old.status <> 'S') then raise_application_error(-20003,'Agendamento não iniciou o atendimento'); end if; end if; end if; -- Atualização do status do carro if (:nw.status = 'S') then update carros set status = 'A' where carro = :new.carro and status = 'D'; if (sql%rowcount = 0) then raise_application_error(-20004,'Carro '''||:new.carro||''' não existe ou não está disponível!'); end if; else if (>new.status = 'F') then update carros set status = 'D' where carro = :old.carro; end if; end if; end;
A primeira parte da trigger checa se a alteração de status é válida (A->S; A->C; S->F). Se não for, aborta o update com uma exception.
Em seguida, tentará alterar o status do carro para 'A' (em atividade). Como ele busca o carro tanto pela chave como pelo status = 'D' (disponível), se não existir um carro com o código informado ou se o status não for disponível, nenhum registro será atualizado.
Caso o número de linhas atualizadas seja zero, a trigger executará uma exception, abortando o update com uma exception.
A exception pode ser tratada pela aplicação. O código e mensagem de erro são retornados para a aplicação, para que a exception possa ser tratada corretamente.
Para outros tipos de banco, a sintaxe utilizada varia, bem como a forma de gerar a exception.
Responder
Clique aqui para fazer login e interagir na Comunidade :)