Array
(
)

Descobrir um erro de chave antes que o mesmo aconteça

Felipe_cduarte
   - 19 out 2004

Fala pessoal !

essa dúvida é meio maluca, mas tava precisando de um lance assim... as vezes temos uma tabela que possui 5 ou + FKs ... entao se excluirmos um registro dessa tabela, teremos um erro de chave se em algumas das outras tabelas tivermos um registro relativo... exemplo

tab1

id_tab1 PK

tab2

id_tab2 PK
id_tab1 FK

tab3

id_tab3 PK
id_tab1 FK

e assim vai ...

se eu tiver registros na tab2 ou tab3, na hora q excluir um registro de tab1 que existir em alguma das outras tabelas vai gerar o erro... a pergunta é: tem como esse erro ser previsto ( sem select.. pq ai é só usar ´NOT IN ( Select id_tab1 from tab2 )´?? nao sei se eu expliquei bem mas quem conseguir entender e puder ajudar eu agradeço

[]´s

Fer_nanda
   - 19 out 2004

Olá Fábio,
Bom, se eu entendi vamos lá.
Voce precisa verificar a integridade antes da exclusão de um registro.. para não craiar uma qry para essa verificação, fizemos uma função que cuida disso...o que faço é passar a sql para essa verificação.
#Código

//Verifica Integridade Referencial
Function IntReferencial(StrSql: string; NomeBaseDados : TSQLConnection): extended;
var
  qryIntReferencial: TSQLQuery;
begin
  Try
    qryIntReferencial := TSQLQuery.Create(Application);

    qryIntReferencial.SQLConnection := NomeBaseDados;

    qryIntReferencial.Close;
    qryIntReferencial.Sql.Clear;
    qryIntReferencial.Sql.Text := StrSql;
    qryIntReferencial.Open;

    Result := qryIntReferencial.FieldByName(´Total´).Value;
  Except
    ShowMessage(´Erro encontrado na verificação de integridade referencial [0016]´);
  end;
end;

Chamada
#Código
    If IntReferencial(´Select Count(EmpCodigo) as Total from Funcionario where EmpCodigo = ´ + edtEmpCodigo.Text, frmMenuPrincipal.SQLConnection1) >= 1 then
    begin
      edit1.SetFocus;
      showmessage(´Exclusão negada, pois existem funcionários vinculados a esta empresa.´);
      Exit;
    end;


Espero que seja isso que esteja procurando :wink:
Até

Felipe_cduarte
   - 20 out 2004

Fala blz ???

a idéia é +- essa, vou seguir o seu exemplo... neste seu módulo vc deve estar tentando excluir uma empresa certo ?? mas se este codigo da empresa fosse FK em outra tabela e se não existisse nenhum funcionario alocada a ela, o Result da função seria 0 e o sistema aceitaria excluir ... concorda ??? continuando com o seu exemplo, se o codigo da empresa fosse FK em mais 5 tabelas, teria q ser feito um bloco if..else if para validar todas as tabelas ... e se alguma tabela que tivesse esta FK fosse criada apos o desenvolvimento deste módulo, o mesmo teria q ser revisto e inserido a funcao... por isso queria encontrar uma formula até mesmo interna do SQL Server para fazer este tipo de validação .. acho q ainda tô enrolado pra explicar mas é isso :P

desde já agradeço pela ajuda

[]´s

PS: lembrei, olha só não estou criticando seu sistema, mas vc levantou uma boa questão pq trabalho com Delphi tb :P , aguardo seu reply

Marcus.magalhaes
   - 20 out 2004

Bom dia Felipe.

Vc pode ter uma idéia com este código :

Select so.name As ´FK name´, sob.name As ´Tbl Filha´, sobj.name As ´Tbl Mae´
From sysreferences sr Inner Join sysobjects so On sr.constid = so.id
Inner Join sysobjects sob On sr.fkeyid = sob.id
Inner Join sysobjects sobj On sr.rkeyid = sobj.id

Nele vc tem o nome da FK, a tabela filha e a tabela Mãe, a partir daí, dá para vc ter idéia de como seguir para validar as diversas tabelas filhas, não importando se sua estrutura de dados mudar.

Espero ter ajudado.

Att,

Felipe_cduarte
   - 20 out 2004

Fala Marcus blz ??

com essa qry dá pra descobrir as chaves, se juntarmos a ideia da Fernanda dá pra fazer, tipo

while ( not Qry.Eof ) do
IntReferencial()

e assim vai hehe..

mas o problema é q eu queria esse resultado em um select, tipo

case
when ( erro de alguma FK ) then ´Não´
else ´Sim´
end as Pode_excluir

+- isso ... mas pelo jeito nao deve dar pra fazer... vou ter q codificar mesmo.

Valeu de novo pela ajuda

[]´s

Marcus.magalhaes
   - 20 out 2004

Blz Cara.

Só uma curiosidade, pq vc quer saber antes e não tratar o erro depois? Assim vc evitar toda uma série de leituras, q podem pesar na sua conexão.

Att,

Felipe_cduarte
   - 21 out 2004

Fala Marcus !

foi mal ai demorar pra responder ... o lance é o seguinte: na nossa aplicação, em um certo módulo, estaremos utilizando um componente checkbox, que tem 4 estados possiveis: marcado e habilitado, desmarcado e habilitado, marcado e desabilitado, desmarcado e desabilitado... queria conseguir com o CASE montar este SQL , que retornaria 1, 2, 3 e 4 por exemplo para cada estado do checkbox ( este SQL seria relativo a tabela mãe, como vc nomeou a mesma). Um desses estados, o marcado e desabilitado, seria o erro de chave, com isso o usuario nao poderia mexê-lo ( pq já se saberia que existem informações relativas ao registro ).. Estou começando agora a estudar as tabelas do sistema ( sysusers, syslogins, etc ...) mas me parece que está SQL não é possivel .. terei que tratá-lo na aplicação

pensei aki vou exemplificar:

situacao 1: existe tab mãe
situacao 2: nao existe tab mãe
situacao 3: erro FK
situacao 4: erro Unique Index

mas de qualquer forma valeu pela ajuda ... se tiver mais algum comentário , manda ver ! 8)