2013-07-03 21 views
10

Próbuję utworzyć relację wiele do wielu w mojej bazie danych MySQL. Mam trzy tabele: Films, Genres i Films_Genres. Używam następujący kod, aby ustawić je:MySQL wiele do wielu relacji z FOREIGN KEYS

CREATE TABLE Films 
( 
    id INT NOT NULL AUTO_INCREMENT, 
    PRIMARY KEY(id), 
    Title VARCHAR(255) 
), 

CREATE TABLE Genres 
( 
    id INT NOT NULL AUTO_INCREMENT, 
    PRIMARY KEY(id), 
    Name VARCHAR(255) 
), 

CREATE TABLE Films_Genres 
(
    film_id INT NOT NULL, 
    genre_id INT NOT NULL, 
    PRIMARY KEY (film_id, genre_id), 
    FOREIGN KEY (film_id) REFERENCES Films(id) ON UPDATE CASCADE, 
    FOREIGN KEY (genre_id) REFERENCES Genres(id) ON UPDATE CASCADE 
) 

Jednak gdy próbuję wstawić niektóre wartości w tabelach z:

INSERT INTO Films (Title) VALUES ('$title') 
INSERT INTO Genres (Name) VALUES ('$genre') 

mogę zobaczyć nowy film w Films tabeli i nowy gatunek w tabeli Genres, ale tabela Films_Genres nie aktualizuje się - nie ma nowych wierszy (sprawdzam przez phpMyAdmin).

Co robię źle?

+0

Wklej kod PHP lub nie możemy Ci pomóc. Czy zweryfikowaliście '$ title' oraz' $ genre'? Itd .. –

+0

Mogę pokazać wyniki z Filmów i Gatunków - działają. Jedynym problemem jest to, że tabela Films_Genres nie dodaje żadnych wierszy. PHP wydaje się w porządku. Im przy użyciu mysqli_query ($ con, $ sql) do wykonania kodu SQL. Czy jednak SQL jest poprawny? – Sharkz

+0

Zakładam, że brak połączenia w filmie "Films_Genres" to twoje pytanie. Jeśli tak jest, musisz powiązać te dwie rekordy samodzielnie. –

Odpowiedz

15

Nic nie zobaczysz w tabeli Films_Genres, dopóki wyraźnie nie wstawisz w nim czegoś. Integralność referencyjna przez PK i FK nie służy do wypełniania twoich stołów.

Kod MySql do wstawiania nowego rekordu w Films_Genres, jeśli jest to nowy film, który odpowiada do nowego gatunku, może wyglądać

INSERT INTO Films (Title) VALUES ('Title1'); 
SET @film_id = LAST_INSERT_ID(); 

INSERT INTO Genres (Name) VALUES ('Genre1'); 
SET @genre_id = LAST_INSERT_ID(); 

INSERT INTO Films_Genres (film_id, genre_id) VALUES(@film_id, @genre_id); 

Na stronie php, aby uzyskać nowo przypisany identyfikator dla autoincremented użytkowanie w terenie $mysqli->insert_id.

Teraz, jeśli chcesz, aby utworzyć nową warstwę i przypisać go do wielu gatunków na raz można zrobić

INSERT INTO Films (Title) VALUES ('Title2'); 
SET @film_id = LAST_INSERT_ID(); 
-- if you get ids of genre from your UI just use them 
INSERT INTO Films_Genres (film_id, genre_id) 
SELECT @film_id, id 
    FROM Genres 
WHERE id IN (2, 3, 4); 

INSERT INTO Films (Title) VALUES ('Title3'); 
SET @film_id = LAST_INSERT_ID(); 
-- if you names of genres you can use them too 
INSERT INTO Films_Genres (film_id, genre_id) 
SELECT @film_id, id 
    FROM Genres 
WHERE Name IN ('Genre2', 'Genre4'); 

Tu jest SQLFiddle demo

+0

Wow! Nie mogłem się spodziewać lepszego anwser! Wielkie dzięki! I love stackoverflow: D – Sharkz

+0

@Sharkz Nie ma za co :) Zobacz zaktualizowaną odpowiedź, aby uzyskać dodatkowe informacje. – peterm

0

Zasadniczo należy wstawić wiersz do w tabeli linków, aby "połączyć" film i gatunek, który właśnie wstawiłeś. Silnik MySQL nie robi tego automatycznie (po prostu nie wie, że te 2 rekordy powinny być w jakiś sposób powiązane) - to jest zrobić po stronie aplikacji lub ręcznie

INSERT INTO Films_Genres (film_id,genre_id) VALUES (1,1) 
0

Musisz wypełnić tabelę "wiele do wielu" samemu sobie, tak działa mysql, niestety nie ma tu automatycznej zgadywanki.