GUJ Discussões   :   últimos tópicos   |   categorias   |   GUJ Respostas

Problemas com Foreign Key no MySQL [RESOLVIDO]


#1

Estou com um pequeno problema: tenho duas tabelas no MySQL, uma chama-se clientes e a outra vendedores. A tabela clientes tem um campo chamado Vendedor (INTEGER) que é uma Foreign Key para o campo ID da tabela vendedores. O problema é que na tabela clientes pode ocorrer de o usuário não querer definir um vendedor para aquele cliente, logo o campo Vendedor da tabela clientes deverá ficar vazio/nulo. Aí é que começa o problema: na hora da inserção o banco de dados lança um erro acusando que a chave estrangeira falhou e etc. Eu não posso remover o relacionamento entre as tabelas pois isso me sujeitaria a erros de integridade referencial, onde um vendedor poderia por acidente ser excluído e então os clientes tornaríam-se registros órfãos.

Alguém tem uma idéia de como eu posso sanar este problema? Desde já agradeço.


#2

nao entendi muito oq vc quis dizer, mais c o campo Vendedor no cliente e um FK nao pode ser nulla,no caso c no seu sistema o campo vendedor possa ser nullo nao coloque ele como Fk na tabela Cliente vlw.


#3

eu sou da opnião do rapaz aqui de cima! acredito eu que se vc chegou em um caso como oq vc citou seu problema está no projeto do banco! tente rever as tabelas e tentar encontrar onde vc errou, pois tem alguma coisa estranha aí amigo!


#4

Cara seja bem vindo ao conceito de CHAVE NATURAL e CHAVE ARTIFICIAL...

Explicando...para controle de Banco de Dados sempre usamos um campo do tipo ID....ele sempre é PK e não pode ser nulo, além de ser auto increment....esta é a chave NATURAL

Porém em alguns casos é interessante que vc use o conceito acima e crie uma segunda ID....e essa nova ID será a chave ARTIFICIAL ou seja ela esta relacionada à parte funcional do seu sistema e não do Banco de Dados...

espero que vc tenha entendido o conceito ( pra falar a verdade eu nem sei se existe... Mas também não sei de onde tirei isso )

[/]'s


#5

eu acho que entendi... aqui uso algo parecido, mais os checks ficam dentro do programa.... não sei se tem como fazer isso via tabela... a não ser que vc crie um registro 0 na tabela de vendedores... ae para de dar o erro....


#6

Giulliano, o que você falou faz sentido, talvez seja a solução do meu problema.

didabeca e alansto, não há nada errado no banco, acho.

É mais ou menos assim:

Notem que na tabela clientes há um campo que aponta para a tabela vendedores, uma chave estrangeira, portanto. O problema é que, às vezes, pode não ser de vontade do usuário escolher um vendedor para o cliente, então a chave estrangeira na tabela clientes deverá ficar nula. O problema é que o banco não permite isso. A solução seria então eu remover a chave estrangeira, mas aí minha integridade referencial vai pro espaço, hehe. O que preciso é que:

-> Para cada cliente cadastrado pode ou não haver um vendedor. Caso haja a escolha de um vendedor, este vendedor deverá "existir" na tabela vendedores.

Ou seja, preciso manter uma chave estrangeira pra garantir que não será escolhida uma ID inválida e também para evitar que um vendedor seja excluído e registros de clientes fiquem com valores órfãos em seus campos.

Não vejo de que outra forma posso fazer isso. Acredito que o banco de dados não esteja incorreto (no seu projeto).

Obrigado a todos pelas respostas.


#7

E se vc criasse uma terceira tabela só de relacionamentos....

-- Table "tb_associa_cliente_vendedor" DDL
CREATE TABLE `tb_associa_cliente_vendedor` (
  `id_cliente` int(11) NOT NULL,
  `id_vendedor` int(11) default NULL,
  PRIMARY KEY  (`id_cliente`),
  KEY `id_vend` (`id_vendedor`),
  CONSTRAINT `id_cli` FOREIGN KEY (`id_cliente`) REFERENCES `tb_cliente` (`id`),
  CONSTRAINT `id_vend` FOREIGN KEY (`id_vendedor`) REFERENCES `tb_vendedor` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

Tabela de Clientes

-- Table "tb_cliente" DDL
CREATE TABLE `tb_cliente` (
  `id` int(11) NOT NULL auto_increment,
  PRIMARY KEY  (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

Tabela Vendedor

-- Table "tb_vendedor" DDL
CREATE TABLE `tb_vendedor` (
  `id` int(11) NOT NULL auto_increment,
  PRIMARY KEY  (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

E aí vc salvaria na tabela de associação somente valores validos nas tabelas cliente e vendedor

a verdade é que existem diversas formas de se fazer isso...só estou te dando uma pequena luz mesmo...boa sorte ae...

[/]s

obs.: código SQL para MySQL 5.0


#8

Ae cara, valew pelo help, foi de muita utilidade.

Entretanto, acredito que o que vou fazer mesmo é excluir a chave estrangeira e torná-la comum. Então, para manter a integridade referencial, terei de fazer um trigger after delete na tabela vendedores para, após algum registro ser excluído, a tabela clientes seja atualizada, setando nulo para os registros que referenciavam (funcionalmente, não tecnicamente) o vendedor excluído.

O fato de eu não fazer nenhuma manobra muito ousada com o banco é que a aplicação aqui na empresa é programada a partir de uma ferramenta RAD, de modo que, se eu quisesse usar uma tabela auxiliar, muito provavelmente acarretar-se-ía uma boa parcela de código adicional nisso.

Mesmo assim, agradeço mais uma vez a ajuda.

Até mais!


#9

Bom, não sei se dá tempo de respoder ainda... mas.. aí vai.

Tente criar a chave estrangeira desta forma:

create table vendedor(
id int not null auto_increment,
...
... ,
constraint pk_vendedor primary key (id)
);

create table cliente(
id int not null auto_increment,
id_vendedor int,
...
... ,
constraint pk_cliente primary key (id),
constraint fk_cliente2vendedor foreign key(id_vendedor) references vendedor(id) on update restrict on delete restrict
);

Espero ter ajudado...


#10