mysql - Como fazer chaves estrangeiras um-para-muitos usando PHP - Stack Overflow em Português
Como fazer chaves estrangeiras um-para-muitos usando PHP [fechada]
noticias   | categorias | tags
id      |     id     | tag_a
noticia_nome |  tag_nome  | tag_b
noticia_id  |            |  ...
|            | tag_j (10 no total)
A coluna tags tem 10 tags, e eu tenho uma noticia que irá usar 4 tags como eu faço uma chave estrangeira (foreign key), para ligar o noticia_id com 4 tags?
editada 9/07/17 às 19:11
perguntada 8/07/17 às 17:51
fechada como não está clara o suficiente por Tiago S, rubStackOverflow, Anderson Carlos Woss, Marcus Nunes, Lucas Costa 27/07/17 às 18:06
Relacionado: pt.stackoverflow.com/a/146432/57801 – Don't Panic 8/07/17 às 18:12
A tabela tags possui 10 coluna? Por quê? E se uma notícia pode possuir 4 tags e uma tag pode ser possuída por várias notícias, a relação será de muitos para muitos, não um para muitos. – Anderson Carlos Woss 9/07/17 às 12:57
Você está confundindo o conceito de coluna com o conceito de tabela.
Observe essa sua tabela:
noticia_id  |            | tag_c
|            | tag_d
|            | tag_e
|            | tag_f
|            | tag_g
|            | tag_h
|            | tag_i
|            | tag_j
Nesta tabela, as linhas não são coisas que tenham muito significado lógico. O que você quer é trabalhar com três tabelas diferentes.
Vejamos como organizar essas tabelas:
Uma notícia é uma coisa que tem um nome e um id. Não é permitido que duas notícias diferentes tenham o mesmo nome.
Uma tag é uma coisa que tem um nome e um id. Não é permitido que duas tags diferentes tenham o mesmo nome.
Você quer categorizar notícias ao colocar tags nelas. Uma notícia pode ter várias tags distintas. Uma mesma tag pode aparecer em várias notícias diferentes. Ou seja, isso é um relacionamento muitos-para-muitos, ou também chamado de M-para-N (ou N-para-N). Não é um relacionamento um-para-muitos como está na sua pergunta. Nota-se também que uma mesma tag não pode aparecer mais de uma vez na mesma notícia e nem uma mesma notícia pode aparecer mais de uma vez em uma mesma tag.
Assim, as suas tabelas ficam desse jeito:
PRIMARY KEY pk_noticia (id),
UNIQUE KEY noticia_nome (nome)
PRIMARY KEY pk_tag (id),
UNIQUE KEY tag_nome (nome)
CREATE TABLE noticia_tag (
id_noticia int(11) NOT NULL,
id_tag int(11) NOT NULL,
PRIMARY KEY pk_noticia_tag (id_noticia, id_tag)
ALTER TABLE noticia_tag ADD CONSTRAINT fk_noticia_tag_noticia FOREIGN KEY (noticia_id) REFERENCES noticia(id);
ALTER TABLE noticia_tag ADD CONSTRAINT fk_noticia_tag_tag FOREIGN KEY (tag_id) REFERENCES tag(id);
CREATE INDEX idx_noticia_tag_noticia ON noticia_tag (id_noticia);
CREATE INDEX idx_noticia_tag_tag ON noticia_tag (id_tag);
Para entender esse script, vamos fazer algumas observações:
A instrução CREATE TABLE é a responsável por criar uma tabela, especificando nela, dentro dos parênteses, quais são as colunas.
Cada coluna na instrução CREATE TABLE começa com o nome da coluna e com o tipo (aqui usamos os tipos int(11) e varchar(50)). Depois do tipo da coluna, podem ser acrescentados modificadores. Os modificadores que usamos aqui são NOT NULL e AUTO_INCREMENT.
O AUTO_INCREMENT diz que o valor da coluna será preenchido automaticamente pelo banco de dados quando ocorrer uma inserção.
O NOT NULL diz que o valor da coluna não pode nunca ser NULL.
As linhas do tipo PRIMARY KEY pk_tabela (id) dizem que o campo id é a chave primária em cada uma dessas tabelas. No caso de uma chave primária composta, há mais do que um campo dentro desses parênteses no PRIMARY KEY, tal como no PRIMARY KEY pk_notica_tag (id_noticia, id_tag).
Nas linhas do tipo PRIMARY KEY, esse nome que aparece entre a palavra KEY e o abre-parêntese é o nome da chave primária. Você não precisa especificar isso se não quiser, podendo usar apenas PRIMARY KEY (id) se preferir. Entretanto, se você não der um nome para a sua chave primária, o banco de dados vai dar o nome PRIMARY automaticamente.
As linhas do tipo UNIQUE KEY têm um formato parecido com a da PRIMARY KEY e servem para especificar quais conjuntos de colunas não podem ser repetidos mesmo não sendo elas as chaves primárias. Cada chave única pode ter um nome, e se você não especificar um nome, o banco de dados vai inventar um nome sozinho com base no nome das colunas escolhidas (mas nem sempre o nome inventado será um bom nome).
Para relacionar quais notícias têm quais tags, usamos a tabela noticia_tag. Essa tabela não contém nada mais além de linhas que casam uma notícia com uma tag. Uma mesma notícia pode aparecer várias vezes, e uma mesma tag também. Entretanto, uma mesma notícia com uma mesma tag só pode aparecer uma vez nesta tabela, uma vez que essa é a chave primária da tabela.
O MySQL têm várias engines diferentes, que são formas distintas de se armazenar tabelas. Para cada tabela estamos usando a engine InnoDB. Isso é feito ao utilizar-se ENGINE=InnoDB após o fecha-perêntese de cada CREATE TABLE. O MySQL têm várias engines diferentes.
Para evitar problemas de encoding, utilizamos UTF-8 para a codificação de textos. É isso o que o DEFAULT CHARSET=utf8 em cada instrução CREATE TABLE quer dizer.
As instruções ALTER TABLE adicionam as chaves estrangeiras. É possível adicioná-las diretamente no CREATE TABLE também, mas prefiro fazer com ALTER TABLE porque assim você pode colocar todas as instruções ALTER TABLE no final do script de criação do banco de dados e com isso não precisa se preocupar com a ordem na qual as tabelas são criadas.
As instruções CREATE INDEX, como o nome já diz, criam índices. Um índice serve para acelerar a busca em uma tabela, evitando-se que essa tenha que ser percorrida linha por linha quando uma busca for realizada. São criados dois índices na tabela pk_notica_tag. Um deles indexa pelo id_tag, e serve para achar rapidamente todas as notícias com uma determinada tag. O outro indexa pelo id_noticia, servindo para achar rapidamente todas as tags existentes em uma determinada notícia.
respondida 9/07/17 às 19:09
Diz a sua instancia de conexão com o banco para fazer isso mais substitua os meus dados pelos seus
`codcidade` INT NOT NULL ,
`descricao` VARCHAR( 50 ) NOT NULL
`codcliente` INT PRIMARY KEY ,
`codvendedor` INT PRIMARY KEY ,
`codvenda` INT PRIMARY KEY ,
`datavenda` DATE NOT NULL
`codcliente` INT,
`codvendedor` INT
ALTER TABLE `clientes` ADD CONSTRAINT `fk_cidade` FOREIGN KEY ( `codcidade` ) REFERENCES `cidade` ( `codcidade` ) ;
ALTER TABLE `vendas` ADD CONSTRAINT `fk_vendas_codcliente` FOREIGN KEY ( `codcliente` ) REFERENCES `clientes` ( ` codcliente ` ) ;
ALTER TABLE `vendas` ADD CONSTRAINT `fk_vendas_codvendedor` FOREIGN KEY ( `codvendedor` ) REFERENCES `vendedores` ( ` codvendedor ` ) ;
editada 8/07/17 às 20:53
respondida 8/07/17 às 18:50
Mas isso não chega nem perto do que ele/ela quer. – Don't Panic 8/07/17 às 19:20
responde então oque ele quer – Nicasio Marques 8/07/17 às 20:34
Já coloquei o que deve ser visto no meu comentário... primeiramente o que está sendo solicitado uma relação de M pra N, como sua resposta não responde a esse quesito, eu lhe alertei..... – Don't Panic 8/07/17 às 20:41