Trước hết "toxi" không phải là một thuật ngữ tiêu chuẩn. Luôn xác định các điều khoản của bạn! Hoặc ít nhất là cung cấp các liên kết có liên quan.
Và bây giờ đến câu hỏi của chính nó ...
Không, bạn sẽ có 3 bảng.
Bạn đang đi đúng hướng khá nhiều, ngoại trừ việc bạn có thể sử dụng bản chất dựa trên tập hợp của SQL để "hợp nhất" nhiều bước trong số này. Ví dụ:gắn thẻ một mục 1 bằng các thẻ:'tag1', 'tag2' và 'tag3' có thể được thực hiện như thế này ...
INSERT IGNORE INTO tagmap (item_id, tag_id)
SELECT 1, tag_id FROM tags WHERE tag_text IN ('tag1', 'tag2', 'tag3');
IGNORE
cho phép điều này thành công ngay cả khi mục đã được kết nối với một số thẻ này.
Điều này giả định rằng tất cả các thẻ bắt buộc đều đã có trong thẻ tags
. Giả sử tag.tag_id
là tự động tăng dần, bạn có thể làm điều gì đó như sau để đảm bảo chúng:
INSERT IGNORE INTO tags (tag_text) VALUES ('tag1'), ('tag2'), ('tag3');
Không có ma thuật. Nếu "mục được kết nối với một thẻ cụ thể" là phần kiến thức bạn muốn ghi lại, thì mục đó sẽ có để có một số loại biểu diễn vật lý trong cơ sở dữ liệu.
Ý bạn là gắn thẻ lại các mục (không phải tự sửa đổi thẻ)?
Để xóa tất cả các thẻ không có trong danh sách, hãy làm như sau:
DELETE FROM tagmap
WHERE
item_id = 1
AND tag_id NOT IN (
SELECT tag_id FROM tags
WHERE tag_text IN ('tag1', 'tag3')
);
Thao tác này sẽ ngắt kết nối mục khỏi tất cả các thẻ ngoại trừ 'tag1' và 'tag3'. Thực hiện CHÈN ở trên và XÓA này lần lượt để "che" cả việc thêm và xóa thẻ.
Bạn có thể chơi với tất cả những thứ này trong SQL Fiddle .
Sửa. Điểm cuối con của FK sẽ không kích hoạt hành động tham chiếu (chẳng hạn như BẬT XÓA CASCADE), chỉ cha mẹ mới thực hiện.
BTW, bạn đang sử dụng giản đồ này vì bạn muốn có các trường bổ sung trong thẻ tags
(bên cạnh tag_text
), đúng? Nếu bạn làm vậy, việc không để mất dữ liệu bổ sung này chỉ vì tất cả các kết nối đã biến mất là hành vi mong muốn.
Nhưng nếu bạn chỉ muốn tag_text
, bạn sẽ sử dụng một giản đồ đơn giản hơn, trong đó việc xóa tất cả các kết nối sẽ giống như xóa chính thẻ:
Điều này không chỉ đơn giản hóa SQL mà còn cung cấp phân cụm tốt hơn .
Thoạt nhìn, "toxi" có thể trông giống như tiết kiệm dung lượng, nhưng điều này thực sự không đúng trong thực tế, vì nó yêu cầu các bảng và chỉ mục bổ sung (và các thẻ có xu hướng ngắn).
Hãy đo lường trước khi bạn quyết định làm điều gì đó như thế này. SQL Fiddle của tôi được đề cập ở trên sử dụng một thứ tự rất có chủ ý của các trường trong bản đồ thẻ tags
PK, vì vậy dữ liệu được nhóm theo cách rất thân thiện với kiểu đếm này (hãy nhớ: Các bảng InnoDB được nhóm lại
). Bạn phải có một số lượng vật phẩm thực sự khổng lồ (hoặc yêu cầu hiệu suất cao bất thường) trước khi điều này trở thành vấn đề.
Trong mọi trường hợp, đo lường trên lượng dữ liệu thực tế!