2012-05-05 3 views
6

MySQL에서 연관 테이블로 구현 된 many-to-many 관계가 있습니다. 나는 아이들을위한 테이블과 부모를위한 테이블을 가지고있다. 자식은 parent_child_link 연관 테이블에 ID가있는 여러 부모를 가질 수 있습니다.PHP 업데이트 MYSQL many-to-many 관계

어린이는 HTML 양식을 통해 업데이트 할 수 있으며 부모는 HTML 다중 선택에 있습니다. 이제 데이터베이스의 레코드를 업데이트해야하지만 내 솔루션은 그리 효율적이지 않습니다. 여기에 내가 무슨 의사에 있어요 :

  1. 업데이트 child_id = X
  2. 이 parent_child_link에서 현재의 모든 연결을 삭제 자식 정보를 어디 child_id = X
  3. 삽입 새로운 협회

이 솔루션 위대한 작품이지만 부모가 바뀌지 않았을 때, 예. 하위의 이름 만 바뀌면 2 개의 불필요한 쿼리가 실행됩니다. 이러한 불필요한 쿼리는 어떻게 피할 수 있습니까? 여러 선택의 부모가 바뀌지 않았는지 확인하는 방법이 있습니까?

물론 나는이 모든 번거 로움을 무시할 수 있습니다. 이미 작동하기 때문에 가능한 한 효율적으로 유지하려고합니다.

답변

0

ON UPDATE CASCADEON DELETE CASCADE을 자식 테이블의 정의로 사용하여 응용 프로그램 계층이 아닌 데이터베이스에서 해결하십시오.

약간 수정 된 예는 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

편집 : 대한 당신의 다 대다 관계는 같은 것을 사용할 수 있습니다

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

이것은 일대일입니다. OP는 피벗 테이블과 다 대다 관계를 유지합니다. – lafor

+0

당신의 오른쪽 라포, 내 잘못. –

+1

응용 프로그램 레이어 외부로 옮기고 싶지만 참조가있는 솔루션이 내 문제를 해결하는 방법을 모르겠다. 지금까지 분석해 보았지만 링크를 제거하기 위해 하위 또는 상위를 삭제할 때 유용합니다. – EsTeGe

0

해결책은 괜찮습니다.
변경 사항이 발생하면 부모를 검색하고 다중 선택 데이터로 확인하는 쿼리를 작성하여 프로세스를 "최적화"할 수 있습니다.
그런 다음 필요에 따라 두 개의 삭제 및 삽입 쿼리 만 수행합니다. 부모님이 실제로 부모님을 바 꾸었을 때, 2 대신에 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); 

그럼 난 그냥) 1) 항목을 삭제하는 (더 이상 존재하지 않는 파악), 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