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

Como realizar SELECT em tabelas que possuem chave estrangeira em tabelas que já tem outra chave estrangeira?

mysql
modelagem
Tags: #<Tag:0x00007fb01c473b40> #<Tag:0x00007fb01c473a00>

#1

Estou modelando um sistema e tenho três tabelas que são:

  • Estado(nome,sigla),
  • Cidade(nome,cod_estado)
  • Endereco(rua,numero,bairro,cep,cod_cidade).

Ocorre que eu não consigo trazer os valores da coluna estado através de SELECT na tabela endereco que só tem uma referencia através da chave estrangeira da tabela cidade.

Alguém pode dar um exemplo de SELECT com a cláusula WHERE na tabela endereco trazendo os valores estado.nome e estado.sigla?

Segue SQL para criação das tabelas:

CREATE TABLE Estado(
cod_estado INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
nome_estado VARCHAR(45) NOT NULL,
sigla_estado VARCHAR(2)
);

CREATE TABLE Cidade(
cod_cidade INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
nome_cidade VARCHAR(45) NOT NULL,
cod_estado INT NOT NULL
);

CREATE TABLE Endereco(
cod_endereco INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
rua VARCHAR(45) NOT NULL,
numero VARCHAR(20) NOT NULL,
bairro VARCHAR(45) NOT NULL,
cep VARCHAR(20) NOT NULL,
cid_cidade INT NOT NULL
);

ALTER TABLE Cidade ADD CONSTRAINT fk_cidade FOREIGN KEY(cod_estado) REFERENCES Estado(cod_estado);

ALTER TABLE Endereco ADD CONSTRAINT fk_endereco FOREIGN KEY(cod_cidade) REFERENCES Cidade(cod_cidade);


#2

Você deve ligar o endereço a cidade e depois ao Estado.

Seria assim:

Select est.nome, est.sigla, cd.nome
from 
Endereco end
 join Cidade cd
  on end.cod_cidade = cd.cod_cidade
 join Estado est
  on est.cod_estado = cd.cod_estado

#3

Então fiz assim e não funcionou. Só funciona se eu colocar estado e cidade como chaves estrangeiras na tabela endereco.


#4

Silvio, faz assim, coloca aqui as construções que você está fazendo. O correto é: chave estrangeira da Cidade na tabela Endereço, Chave estrangeira do Estado na tabela de Cidade.


#5

Se o layout das suas tabelas são assim, só lhe dou uma dica:

##Pare e modele novamente.

Porque está errado.!


#6

Nao entendi sua dica.

  • Porque está errado?
  • Se ele for modelar novamente, o que ele precisa fazer diferente?

#7

A chave estrangeira é um recurso pra garantir integridade referencial, nao influencia no resultado do select.

O código passado pelo @wendelnos parece correto, qual problema você está tendo?

Aqui um exemplo disso funcionando: http://sqlfiddle.com/#!15/d327d/3/0


#8

Cade as chaves das tabelas?
Cade as relações?

As informações da pergunta faltam para ter uma certeza de tudo, ai você olha bem em cidade tem relação com Estado pelo campo cod_estado? e no estado não tem a chave?

Sinceridade, não podemos adivinhar, a pergunta tem que ser bem elaborada para não ter duvidas na hora da solução é isso.


#9

Depende! Influência sim em diversos casos principalmente em desempenho de leitura na junção das tabelas.


#10

Esse modelo que estou dizendo não é correto, colocar Estado sem identificação de chave primária quando for mudar algum estado então vou ter que atualizar toda tabela de cidade?

Pense um pouco!


#11

O fato dele nao ter falado de chaves nao implica que elas nao existem, talvez simplesmente nao seja relevante ao problema. Ele menciona existir chaves estrangeiras. O fato é que elas nao mudam o resultado do Select, que é a dúvida dele.

Uma coisa é você nao entender a pergunta, e aí sim é normal pedir mais informaçao. Mas isso nao quer dizer que ninguém tenha entendido.

O que influencia no desempenho sao os indices associados a tabela. Acontece que alguns bancos (nem todos), criam indices implicitamente quando você cria uma chave estrangeira. Mas enfim, o resultado continua o mesmo. O select pode ficar mais lento, mas nao deixa de funcionar por nao ter chave estrangeira.

Em toda modelagem há riscos de se cometer algum erro. Há vantagens de se ter a sigla do estado como chave. Em muitos casos isso irá evitar um join desnecessário pois a sigla já dá informaçao suficiente para o usuário saber de qual estado se trata.
Apesar de dar preferências pra ids gerados automaticamente, eu acho que a vantagem acima e o fato da última modificaçao em estados brasileiros ter ocorrido há 30 anos, me deixariam confortável o bastante para seguir essa abordagem.

Falando em pensar… Acho que até pela sua posiçao no GUJ você deveria pensar um pouco respeitar os outros. Dizer em negrito que algo está errado (sem dizer os motivos), mandar pessoas que nao concordam com seu ponto de vista “pensar um pouco”, nao é um comportamento que estimule discussoes saudáveis.


#12

Aqui você disse a mesma coisa que eu relatei como problema![quote=“AbelBueno, post:11, topic:347106”]
Em toda modelagem há riscos de se cometer algum erro. Há vantagens de se ter a sigla do estado como chave. Em muitos casos isso irá evitar um join desnecessário pois a sigla já dá informaçao suficiente para o usuário saber de qual estado se trata.
Apesar de dar preferências pra ids gerados automaticamente, eu acho que a vantagem acima e o fato da última modificaçao em estados brasileiros ter ocorrido há 30 anos, me deixariam confortável o bastante para seguir essa abordagem.
[/quote]

Aqui há um erro conceitual, não pode utilizar o UF como chave de relação porque se a UF mudar vou ter problemas na tabela que a recebe, isso é um erro grave que acontece em muitos sistema. Ai se pode dizer Unidade Federativa não muda, eu também pensava assim até o dia que criaram um nova a Tocantis … Então use na relação sempre número e o UF como indice que não repete e na tabela cidade use sempre a id da UF.

e FALEI EM PENSAR no sentido do problema do usuário e foi você que me indagou e eu respondi em cima disso, e não me leve a mau ser ou não ser um operador diferente não muda nada em relação a responder questionamento e eu não fui desrespeitoso com você, é só apontei o problema de fazer assim!


#13

Bom dia então não consigo selecionar as colunas da tabela estado. Vou dar um exemplo de select que tentei.
SELECT rua,numero,bairro,cep,cidade.nome,estado.nome, estado.sigla FROM Endereco
INNER JOIN Cidade Cidade INNER JOIN Estado
ON Endereco.cod_cidade = cidade.cod_cidade
ON Cidade.cod_estado = Estado.cod_estado
WHERE Endereco.cod_endereco = 1;

Essa query não funciona, só funciona se eu fizer inner join com Endereco INNER JOIN com Cidade entendeu
`


#14

Mas é isso que está no meu banco. Eu sou novado aqui no GUJ não sei se dá para enviar imagem senão enviaria uma imagem do ERR das tabelas


#15

Bom dia eu havia me esquecido mas tem sim, as tabelas foram criadas assim

CREATE TABLE Estado(
cod_estado INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
nome_estado VARCHAR(45) NOT NULL,
sigla_estado VARCHAR(2)
);

CREATE TABLE Cidade(
cod_cidade INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
nome_cidade VARCHAR(45) NOT NULL,
cod_estado INT NOT NULL
);

CREATE TABLE Endereco(
cod_endereco INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
rua VARCHAR(45) NOT NULL,
numero VARCHAR(20) NOT NULL,
bairro VARCHAR(45) NOT NULL,
cep VARCHAR(20) NOT NULL,
cid_cidade INT NOT NULL
);

ALTER TABLE Cidade ADD CONSTRAINT
fk_cidade FOREIGN KEY(cod_estado) 
REFERENCES Estado(cod_estado);

ALTER TABLE Endereco ADD CONSTRAINT 
fk_endereco FOREIGN KEY(cod_cidade) 
REFERENCES Cidade(cod_cidade);

#16

Mas isso é esperado. Endereço tem um relacionamento com Cidade que por sua vez tem relacionamento com Estado.
Para pegar os dados de Estado você precisa passar por Cidade mesmo.[quote=“Silvio_Dasilvamartin, post:13, topic:347106”]
SELECT rua,numero,bairro,cep,cidade.nome,estado.nome, estado.sigla FROM Endereco
INNER JOIN Cidade Cidade INNER JOIN Estado
ON Endereco.cod_cidade = cidade.cod_cidade
ON Cidade.cod_estado = Estado.cod_estado
WHERE Endereco.cod_endereco = 1;
[/quote]

O erro aqui é que a parte ON precisa acompanhar o INNER JOIN, no seu caso ficaria assim:

SELECT rua,numero,bairro,cep,cidade.nome,estado.nome, estado.sigla 
FROM Endereco
INNER JOIN Cidade Cidade ON Endereco.cod_cidade = cidade.cod_cidade 
INNER JOIN Estado ON Cidade.cod_estado = Estado.cod_estado
WHERE Endereco.cod_endereco = 1;

#17

Irmão Valeu mesmo funcionou agora