2012-05-05 72 views
6

Tôi có mối quan hệ nhiều-nhiều, được triển khai với một bảng kết hợp trong MySQL. Tôi có một bàn cho trẻ em và một bàn cho cha mẹ. Một đứa trẻ có thể có nhiều cha mẹ, được lưu trong bảng liên kết parent_child_link với ID của họ.Cập nhật PHP MYSQL quan hệ nhiều-nhiều-nhiều

Trẻ em có thể được cập nhật thông qua biểu mẫu HTML, cha mẹ có nhiều lựa chọn HTML. Bây giờ tôi cần cập nhật bản ghi trong cơ sở dữ liệu, nhưng giải pháp của tôi không hiệu quả lắm. Dưới đây là trong giả những gì tôi làm:

  1. Cập nhật các thông tin con nơi child_id = x
  2. Xóa tất cả các hiệp hội hiện nay ở parent_child_link nơi child_id = x
  3. Chèn các hiệp hội mới

Giải pháp này hoạt động tốt, nhưng khi cha mẹ không thay đổi, ví dụ chỉ có tên của đứa trẻ đã được thay đổi, sau đó có 2 truy vấn không cần thiết thực hiện. Làm cách nào để tránh những truy vấn không cần thiết này? Có cách nào để kiểm tra xem cha mẹ trong đa lựa chọn có thay đổi không?

ofcourse Tôi chỉ có thể bỏ qua tất cả những rắc rối này, bởi vì nó đã hoạt động, nhưng tôi thực sự muốn giữ mọi thứ hiệu quả nhất có thể.

Trả lời

0

Hãy thử giải quyết nó trong cơ sở dữ liệu, không phải trong lớp ứng dụng bằng cách sử dụng ON UPDATE CASCADEON DELETE CASCADE trong định nghĩa của bảng con.

Một ví dụ hơi sửa đổi thành các trang web 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; 

Kiểm tra các tài liệu ở đây: http://dev.mysql.com/doc/refman/5.5/en/innodb-foreign-key-constraints.html

EDIT: Đối với bạn nhiều-nhiều mối quan hệ bạn có thể sử dụng một cái gì đó như:

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

Hy vọng điều này sẽ hữu ích.

+0

Đây là một đối một; OP có mối quan hệ nhiều - nhiều với bảng tổng hợp. – lafor

+0

Lafor đúng của bạn, xấu của tôi. –

+1

Tôi rất thích di chuyển nó ra ngoài lớp ứng dụng, nhưng tôi không thấy giải pháp của bạn với các tham chiếu sẽ giải quyết vấn đề của tôi như thế nào. Theo như tôi đã quản lý để phân tích nó, nó sẽ hữu ích khi xóa một đứa trẻ hoặc cha mẹ (để thoát khỏi liên kết). – EsTeGe

0

Giải pháp của bạn là tốt.
Trong trường hợp của bạn, bạn có thể "tối ưu hóa" quy trình bằng cách thực hiện truy vấn để truy xuất cha mẹ và kiểm tra dữ liệu đa lựa chọn nếu có bất kỳ thay đổi nào xảy ra.
Sau đó, bạn chỉ thực hiện hai truy vấn xóa và chèn nếu cần. Đối tác là khi bạn thực sự thay đổi cha mẹ, thì sẽ có 3 truy vấn thay vì 2.
Vì vậy, bạn nên hỏi bạn liệu bạn có thường xuyên sửa đổi cha mẹ hay không. Trong trường hợp này, bạn nên dính vào giải pháp ban đầu của mình để tránh truy vấn chọn thêm.
Nếu bạn nghĩ rằng cha mẹ sẽ không được cập nhật thường xuyên, thì bạn có thể đi với giải pháp trên. Khi bạn cập nhật thông tin con chỉ, chỉ có một truy vấn được thực hiện. Khi bạn cũng cập nhật cha mẹ, 3 truy vấn được thực hiện.
Khi bạn đi với giải pháp thứ hai, các truy vấn xóa và chèn có thể được tối ưu hóa để chỉ thực hiện những gì được yêu cầu (chỉ xóa cha mẹ không phải là cha mẹ của mình nữa và chỉ chèn các liên kết gốc mới).
Chức năng mảng PHP có thể hữu ích cho điều đó.

0

Nếu bạn muốn giữ cách thức hiện tại của bạn, nhưng chỉ cần tối ưu hóa, bạn có thể bọc các truy vấn trong câu lệnh IF.

Giống như:

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

7

Tôi có cùng một câu hỏi và tìm ra giải pháp của tôi như tôi đang đọc.

Khi tôi sẵn sàng xử lý các mục đã gửi, trước tiên tôi thực hiện truy vấn để nhận các liên kết hiện tại và gọi mảng đó là $ original_list. Danh sách gửi tôi sẽ gọi $ submitted_list.

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

Sau đó, tôi chỉ cần tìm ra 1) mục cần xóa (không còn tồn tại) và 2) mục cần thêm (liên kết mới). Các mục trong cả hai danh sách không được chạm vào.

$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 
} 

Rất muốn biết người khác có cảm thấy đây là giải pháp hợp lệ hay không.

+1

Vâng, đây là cách tôi đã thực hiện các nội dung tương tự trong quá khứ. bình thường tôi sẽ đi với delte -> chèn phương pháp tiếp cận nhưng đó có thể là vấn đề nếu ID của trẻ em được tham chiếu ở nơi khác, chẳng hạn như bạn đang thêm nhiều mục giá vào sản phẩm và ID giá được tham chiếu từ giỏ hàng . không thể thay đổi ID khi giá kỹ thuật không thay đổi. – jammypeach

Các vấn đề liên quan