2011-12-15 46 views
7

Tôi có 3 bảng: nha sĩ, nhóm và liên kết nhóm. Nhiều nha sĩ liên kết với nhiều nhóm thông qua bảng groupdentlink. Vì vậy, tôi đang cố gắng thực hiện một truy vấn, nơi nó sẽ chèn hàng vào groupdentlink (liên kết tất cả các nha sĩ trong tiểu bang với tất cả các nhóm trong tiểu bang) nhưng chỉ khi những hàng đó đã không tồn tại. Tóm lại, tôi muốn thêm các hàng mới mà không ghi đè các hàng hiện có hoặc sao chép chúng.Chèn nơi không tồn tại mà không có khóa chính

Vì vậy, các ý định của truy vấn là một cái gì đó như:

INSERT INTO groupdentlink (f_dent_id, f_group_id, f_schedule_id) 
VALUES ('$_POST[id]', '$groupid', '$scheduleid') 
WHERE NOT EXISTS ('$_POST[id]', '$groupid') 

Và tôi không có bất kỳ khóa chính trong bảng groupdentlink.

Cảm ơn bạn trước!

Trả lời

18

Nếu bạn thực sự muốn viết riêng truy vấn (làm việc) của bạn ..


INSERT INTO groupdentlink (
    f_dent_id, f_group_id, f_schedule_id 
) SELECT 
    '$_POST[id]' f_dent_id, 
    '$groupid' f_group_id, 
    '$scheduleid' f_schedule_id 
FROM DUAL 
WHERE NOT EXISTS (
    SELECT 1 
    FROM `groupdentlink` 
    WHERE 
    f_dent_id = '$_POST[id]' AND f_group_id = '$groupid' 
    LIMIT 1 -- will stop mysql to stop searching after first match 
) 

... nhưng MySQL có thể xử lý tất cả cho bạn!


Bạn không cần phải khóa chính để làm cho MySQL xử lý việc này cho bạn, bạn nên thêm một UNIQUE chế phím trên bộ kết hợp của hai cột.

Truy vấn để thêm khóa duy nhất dent_group_uniq_key vào groupdentlink.

ALTER TABLE groupdentlink ADD UNIQUE KEY `dent_group_uniq_key` (
    f_dent_id, f_group_id 
); 

Sau đó sử dụng INSERT IGNORE trên truy vấn của bạn:

INSERT IGNORE INTO groupdentlink (
    f_dent_id, f_group_id, f_schedule_id 
) VALUES (
    '$_POST[id]', '$groupid', '$scheduleid' 
) 

INSERT IGNORE sẽ cố gắng để chèn một hàng để bàn của bạn, nếu nó không thành công do một trở ngại chính nó sẽ hoạt động như không có gì xảy ra.

+0

OK, nhưng bạn sẽ không gặp lỗi nếu nó không thành công vì các lý do khác nhau, như vi phạm ràng buộc khoá ngoại. – greyfairer

+0

@greyfairer Nó sẽ chỉ "KHỎI" nếu chèn không thành công do khóa trùng lặp, các ràng buộc khóa ngoài vẫn được áp dụng. –

+0

Cảm ơn bạn rất nhiều. Tôi đang sử dụng phương pháp thứ hai: Khóa duy nhất từ ​​các cột được kết hợp vì nó có vẻ đơn giản hơn đối với tôi. –

2

Bạn gần như đã nhận được nó! Bạn có thể sử dụng câu lệnh chọn để nạp câu lệnh chèn. Chỉ cần làm điều này:

INSERT INTO groupdentlink (f_dent_id, f_group_id, f_schedule_id) 
SELECT '$_POST[id]', '$groupid', '$scheduleid' 
WHERE 
    NOT EXISTS (
    select 
     1 
    from 
     groupdentlink 
    where 
     f_dent_id = $_POST[id] 
     and f_group_id = '$groupid' 
    ) 
+0

hmm. Dưới đây là câu hỏi của tôi: "INSERT INTO groupdentlink (f_dent_id, f_group_id, f_schedule_id) \t SELECT '$ _POST [id]', '$ rowv [id]', '$ row [f_sched_id] \t ĐÂU \t NOT EXISTS ( \t SELECT 1 TỪ groupdentlink ĐÂU f_dent_id = '$ _POST [id] vÀ f_group_id =' $ gROUPID" ... và tôi nhận được một lỗi cú pháp –

+0

Bạn cần paren bế mạc vào mệnh đề tồn tại. – Eric

+0

... cố định mà vẫn không hoạt động Oy :( –

4
INSERT INTO groupdentlink (f_dent_id, f_group_id, f_schedule_id) 
SELECT '$_POST[id]', '$groupid', '$scheduleid' FROM dual 
WHERE NOT EXISTS (
    select * from groupdentlink 
    where f_dent_id='$_POST[id]' 
    and f_group_id='$groupid' 
) 

Và tôi nghĩ bạn có thể tạo một khóa chính composit trên sự kết hợp (f_dent_id, f_group_id) chỉ để chắc chắn.

+0

Là một mẹo, sử dụng '1' thay vì' * 'trên câu lệnh' tồn tại' của bạn để bạn không cố gắng kéo trở lại một cột lớn được đặt trong bộ nhớ. Tốc độ truy vấn một chút (có thể có tác động lớn lớn hơn truy vấn nhận được, và phụ thuộc vào động cơ). – Eric

+0

@Eric, đó không phải là trường hợp. Xem [Documents] (http://dev.mysql.com/doc/refman/5.0/en/exists-and-not-exists-subqueries.html): Theo truyền thống, truy vấn con EXISTS bắt đầu bằng SELECT *, nhưng nó có thể bắt đầu với SELECT 5 hoặc SELECT column1 hoặc bất cứ điều gì cả. MySQL bỏ qua danh sách SELECT trong truy vấn con như vậy, vì vậy nó không tạo ra sự khác biệt nào. –

+0

Ah, MySQL không làm điều đó - các phiên bản cũ hơn của SQL Server sử dụng (không biết nếu họ vẫn làm), và đó là nơi mà tất cả công việc của tôi được thực hiện. Tôi sử dụng nó như là một thực hành tốt nhất. – Eric

1
INSERT INTO groupdentlink (f_dent_id, f_group_id, f_schedule_id) 
VALUES ('$_POST[id]', '$groupid', '$scheduleid') 
WHERE NOT EXISTS (
    select * from groupdentlink 
    where f_dent_id='$_POST[id]' 
    and f_group_id='$groupid' 
) 

Và tôi nghĩ bạn có thể tạo khóa chính kết hợp trên kết hợp (f_dent_id, f_group_id).

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