web-dev-qa-db-ja.com

MySQLとFOREIGNKEYSとの多対多の関係

MySQLデータベースに多対多の関係を作成しようとしています。 3つのテーブルがあります:FilmsGenresおよびFilms_Genres。次のコードを使用して設定します。

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
)  

しかし、私がいくつかの値をテーブルに挿入しようとすると:

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

新しい映画はFilmsテーブルに、新しいジャンルはGenresテーブルにありますが、Films_Genresテーブルは更新されません-新しい行はありません(phpMyAdminで確認しています)。

私は何が間違っているのですか?

12
Sharkz

Films_Genresテーブルに何かを明示的に挿入するまで、テーブルには何も表示されません。 PKおよびFKによる参照整合性は、テーブルにデータを入力するためのものではありません。

Films_Genresに新しいレコードを挿入するためのMySqlコードは、新しいジャンルに対応する新しい映画の場合、次のようになります。

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);

自動インクリメントフィールドに新しく割り当てられたIDを取得するには、php側で $mysqli->insert_idを使用します

新しい映画を作成して、一度に複数のジャンルに割り当てたい場合は、次のことができます。

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');

これはSQLFiddleデモです

15
peterm

基本的に、リンクテーブルにも行を挿入して、挿入したばかりの映画とジャンルを「リンク」する必要があります。Mysqlエンジンは自動的にそれを行いません(これらの2つのレコードが必要であることを単に認識していません)。何らかの形で関連している)-これはアプリケーション側で、または手動で実行する必要があります

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

自分で多対多のテーブルに入力する必要があります。これがmysqlの動作方法です。残念ながら、ここでは自動推測作業は実行されません。

0
silkfire