まず第一に、「トキシ」は標準的な用語ではありません。常に用語を定義してください!または、少なくとも関連するリンクを提供します。
そして今、質問自体に...
いいえ、3つのテーブルがあります。
SQLのセットベースの性質を使用してこれらのステップの多くを「マージ」できることを除いて、あなたはほぼ正しい方向に進んでいます。たとえば、アイテム1に「tag1」、「tag2」、「tag3」のタグを付けると、次のようになります...
INSERT IGNORE INTO tagmap (item_id, tag_id)
SELECT 1, tag_id FROM tags WHERE tag_text IN ('tag1', 'tag2', 'tag3');
IGNORE
アイテムがこれらのタグの一部にすでに接続されている場合でも、これを成功させることができます。
これは、必要なすべてのタグがすでにtags
にあることを前提としています 。 tag.tag_id
を想定 は自動インクリメントです。次のようにして、確実に次のようにすることができます。
INSERT IGNORE INTO tags (tag_text) VALUES ('tag1'), ('tag2'), ('tag3');
魔法はありません。 「アイテムが特定のタグに接続されている」が記録したい知識の一部である場合、それは データベースにある種の物理的表現を持たせるため。
アイテムにタグを付け直す(タグ自体を変更しない)という意味ですか?
リストにないすべてのタグを削除するには、次のようにします。
DELETE FROM tagmap
WHERE
item_id = 1
AND tag_id NOT IN (
SELECT tag_id FROM tags
WHERE tag_text IN ('tag1', 'tag3')
);
これにより、「tag1」と「tag3」を除くすべてのタグからアイテムが切断されます。上記のINSERTを実行し、このDELETEを次々に実行して、タグの追加と削除の両方を「カバー」します。
SQLFiddle でこれらすべてを試すことができます。 。
正しい。 FKの子エンドポイントは、参照アクション(ON DELETE CASCADEなど)をトリガーせず、親のみがトリガーします。
ところで、tags
に追加のフィールドが必要なため、このスキーマを使用しています (tag_text
の横 )、 右?その場合、すべての接続が失われたという理由だけでこの追加データを失わないことが望ましい動作です。
ただし、tag_text
が必要な場合 、すべての接続を削除することはタグ自体を削除することと同じである、より単純なスキーマを使用します:
これにより、SQLが単純化されるだけでなく、クラスタリング も向上します。 。
一見、「toxi」はスペースを節約しているように見えるかもしれませんが、追加のテーブルとインデックスが必要になるため(タグは短くなる傾向があるため)、実際にはそうではない場合があります。
このようなことをする前に測定してください。上記の私のSQLFiddleは、tagmap
のフィールドの非常に慎重な順序を使用しています PKなので、データはこの種のカウントに非常に適した方法でクラスター化されます(InnoDBテーブルはクラスター化されています
)。これが問題になる前に、本当に大量のアイテムを持っている必要があります(または非常に高いパフォーマンスが必要です)。
いずれにせよ、測定 現実的な量のデータについて!