2012-05-05 16 views
6

多対多の関係を持っていますが、これはMySQLの関連テーブルで実装されています。私は子供のためのテーブルと両親のためのテーブルを持っています。子は複数の親を持つことができ、parent_child_link関連テーブルにIDで保存されます。PHPの更新MySQLの多対多の関係

子供はHTML形式で更新することができ、両親はHTMLの複数選択になります。今私はデータベースのレコードを更新する必要がありますが、私のソリューションはそれほど効率的ではありません。ここで私は何をすべきか擬似コードである:

  1. 更新child_id = X
  2. がparent_child_linkに現在のすべての関連付けを削除した子情報どこchild_id = X
  3. 挿入し、新たな団体

このソリューション偉大な作品が、親が変更されていないとき、例えば子の名前だけが変更された場合、不要な2つのクエリが実行されます。これらの不要なクエリを避けるにはどうすればよいですか?複数選択の親が変更されていないかどうかを確認する方法はありますか?

もちろん私はこのすべての面倒を無視することができます、それはすでに機能しているので、私は本当に物事を可能な限り効率的に保つことが大好きです。

答えて

0

子テーブルの定義にON UPDATE CASCADEON DELETE CASCADEを使用して、アプリケーション層ではなくデータベースで解決してみてください。

A、わずかに修正された例MySQLの部位を形成する:

CREATE TABLE parent (id INT NOT NULL, 
        PRIMARY KEY (id) 
) ENGINE=INNODB; 

CREATE TABLE child (id INT, parent_id INT, 
        INDEX par_ind (parent_id), 
        FOREIGN KEY (parent_id) REFERENCES parent(id) 
         ON DELETE CASCADE ON UPDATE CASCADE 
) ENGINE=INNODB; 

は、ここにドキュメントをチェックアウト:http://dev.mysql.com/doc/refman/5.5/en/innodb-foreign-key-constraints.html

EDIT:あなたはのようなものを使用することができ、あなたの多対多の関係の場合:

CREATE TABLE parent_child_link (
        parent_id INT NOT NULL, 
        child_id INT NOT NULL, 
        PRIMARY KEY(parent_id, child_id), 
        FOREIGN KEY (parent_id) REFERENCES parent(id) 
         ON DELETE CASCADE ON UPDATE CASCADE, 
        FOREIGN KEY (child_id) REFERENCES child(id) 
         ON DELETE CASCADE ON UPDATE CASCADE 
); 

これが役に立ちます。

+0

これは1対1です。 OPには、ピボットテーブルと多対多の関係があります。 – lafor

+0

あなたの右のラフォー、悪いです。 –

+1

私はアプリケーションレイヤーの外に移動したいと思っていますが、私の問題を解決するためのリファレンスがどのように解決されているのか分かりません。私が分析した限りでは、子や親を削除すると(リンクを削除するために)便利です。 – EsTeGe

0

解決策は問題ありません。
親が取得するクエリを作成し、変更が発生した場合に複数選択データで確認することで、プロセスを「最適化」することができます。
次に、必要に応じて2つの削除および挿入照会のみを実行します。カウンターパートは、親を実際に変更したときに、2つではなく3つのクエリが表示されるということです。
親が頻繁に変更されるかどうか尋ねてください。この場合、特別な選択クエリを避けるために、元のソリューションに固執する必要があります。
親が頻繁に更新されないと思われる場合は、上記の解決策に進むことができます。子情報のみを更新すると、1つのクエリのみが実行されます。親も更新すると、3つのクエリが実行されます。
削除と挿入のクエリを最適化して、必要なものだけを実行することができます(親のリンクではない親を削除し、新しい親リンクのみを挿入する)。
PHP配列関数はそれに役立ちます。

0

現在の方法をそのままにして、最適化したい場合は、IF文でクエリをラップすることができます。

同様:

if (isset ($parent_name_change)){ // run query }

7

私は同じ質問を持っていると私は読んでいたとして、私の解決策を考え出しました。

提出されたエントリを処理する準備ができたら、まず現在の関連付けを取得し、その配列$ original_listを呼び出すためのクエリを実行します。投稿されたリスト$ submitted_listと呼ぶ。

$original_list = array(3,5,7); 
$submitted_list = array(1,2,3); 

次に、削除するアイテム(存在しなくなりました)と2)追加するアイテム(新しい関連付け)を把握するだけで済みます。両方のリストの項目には触れません。

$delete_list = array_diff($original_list, $submitted_list); 
$insert_list = array_diff($submitted_list, $original_list); 

foreach($delete_list as $item) { 
    // delete $item from DB 
} 

foreach($insert_list as $item) { 
    // insert item in db 
} 

他人がこれを有効な解決策と感じているかどうか知りたいですか。

+1

これは私が過去に似たようなことをやったことです。通常、私はdelte - > insertメソッドを使うつもりですが、子供のIDが別の場所で参照されていると問題が発生する可能性があります。例えば、商品に複数の価格エントリを追加し、価格IDをカートから参照している。価格が技術的に変化していないときにIDを変更することはできません。 – jammypeach