En primer lugar, "toxi" no es un término estándar. Siempre define tus términos! O al menos proporcionar enlaces relevantes.
Y ahora a la pregunta en sí...
No, tendrás 3 mesas.
Está prácticamente en el camino correcto, con la excepción de que puede usar la naturaleza basada en conjuntos de SQL para "combinar" muchos de estos pasos. Por ejemplo, etiquetar un elemento 1 con etiquetas:'etiqueta1', 'etiqueta2' y 'etiqueta3' se puede hacer así...
INSERT IGNORE INTO tagmap (item_id, tag_id)
SELECT 1, tag_id FROM tags WHERE tag_text IN ('tag1', 'tag2', 'tag3');
El IGNORE
permite que esto funcione incluso si el elemento ya está conectado a algunas de estas etiquetas.
Esto supone que todas las etiquetas requeridas ya están en tags
. Asumiendo tag.tag_id
es de incremento automático, puede hacer algo como esto para asegurarse de que sean:
INSERT IGNORE INTO tags (tag_text) VALUES ('tag1'), ('tag2'), ('tag3');
No hay magia. Si "el elemento está conectado a una etiqueta en particular" es una parte del conocimiento que desea registrar, entonces tendrá tener algún tipo de representación física en la base de datos.
¿Te refieres a volver a etiquetar elementos (sin modificar las etiquetas en sí)?
Para eliminar todas las etiquetas que no están en la lista, haga algo como esto:
DELETE FROM tagmap
WHERE
item_id = 1
AND tag_id NOT IN (
SELECT tag_id FROM tags
WHERE tag_text IN ('tag1', 'tag3')
);
Esto desconectará el artículo de todas las etiquetas excepto 'tag1' y 'tag3'. Ejecute el INSERT anterior y este DELETE uno tras otro para "cubrir" tanto la adición como la eliminación de etiquetas.
Puedes jugar con todo esto en el SQL Fiddle .
Correcto. Un extremo secundario de un FK no desencadenará una acción referencial (como ON DELETE CASCADE), solo lo hará el principal.
Por cierto, está utilizando este esquema porque desea campos adicionales en tags
(junto a tag_text
), ¿derecho? Si lo hace, no perder estos datos adicionales solo porque todas las conexiones se han ido es el comportamiento deseado.
Pero si solo quisieras el tag_text
, usaría un esquema más simple en el que eliminar todas las conexiones sería lo mismo que eliminar la etiqueta en sí:
Esto no solo simplificaría el SQL, sino que también proporcionaría una mejor clustering .
A primera vista, puede parecer que "toxi" está ahorrando espacio, pero en realidad podría no ser así en la práctica, ya que requiere tablas e índices adicionales (y las etiquetas tienden a ser cortas).
Mida antes de decidir hacer algo como esto. Mi SQL Fiddle mencionado anteriormente usa un orden de campos muy deliberado en el tagmap
PK, por lo que los datos se agrupan de una manera muy amigable para este tipo de conteo (recuerde:Las tablas InnoDB están agrupadas
). Tendría que tener una cantidad realmente enorme de elementos (o requerir un rendimiento inusualmente alto) antes de que esto se convierta en un problema.
En cualquier caso, medir en cantidades realistas de datos!