Autor Zpráva
kozusnikjan
Profil *
Ahoj,
potřeboval bych znát váš názor. Mám tabulku files a chci soubory z této tabulky namapovat k textům, úkolům atd... a nevím, které z těchto dvou řešení je lepší:

1) mít pro každou tabulku novou mapovací tabulku - tzn.
pro texty bude tabulka texts, texts_file (object_id, file_id) a tabulka files
to samé třeba pro úkoly -> tedy tasks, tasks_files, files
obdobně pro galerie, zprávy atd....

2) mít jednu mapovací tabulku - tzn.
bude jedna globáblní mapovací tabulka třeba map_files - ta bude mít sloupce file_id, object_id, object_table, tzn pro texty nějak takto:
texty v tabulce texts a soubory k ní budou namapovány v tabulce map_files takto: (id souboru, id textu, texts)
pro galerie takto: (id souboru, id galerie, galleries)

Které řešení je podle Vás lepší? Co se týče rychlosti, atd...? Zatím používám první metodu ale jde mi o to, že musím pro každou novou tabulku vytvářet další mapovací tabulku... tak uvažuji, že přejdu na 2. řešení, ale zase nevím, jak to bude s rychlostí při 1000+ záznamech.

Děkuji za vaše reakce
Kajman
Profil
Pokud může být jeden soubor použit k více textům a jsou to tedy opravdu jen vazební tabulky, tak bych se nebál dělat variantu 1. Ve druhé variantě přijdete o možnost cizích klíčů.

Je tu ještě třetí varianta - jedna tabulka ale více sloupců, viz.
SQL antipattern?
ale to vlákno se změřuje na situaci, kdy je jeden soubor maximálně jen k jednomu textu.
kozusnikjan
Profil *
No je to tak, že jeden soubor je vždycky pouze k jednomu textu/galerii/úkolu....
Jakto, že bych přišel ve druhé variantě o možnost cizích klíčů? Moc to nechápu. Přece mám stejný počet možností stejné možnosti kombinování díky tomu třetímu sloupci, který určuje, ze které tabulky je objekt, ke kterému mapuji.

Podle vašeho odkazu tedy jestli to chápu dobře to má být uděláno takto:

texts - id, title....
files - id, title, path, ....
map_files - object_table (texts, galleries, tasks,...), text_id, gallery_id, task_id

I když jsem tomu vláknu, na které odkazujete věnoval dost času, nechápu podstatu tohoto řešení. Píše tam něco v tomto smyslu:
"Nebo-li musíš mít sloupec pro každou z vázaných tabulek. Varianta (2) neumožňuje vytvořit cizí klíč nad sloupcem comments.id." - co tím myslí? Děkuji
juriad
Profil
Přečti si tu mou odkázanou prezentaci. http://www.slideshare.net/billkarwin/sql-antipatterns-strike-back (od strany 33)
Jediné správné řešení neexistuje, vždy záleží na tom, co od databázového schématu očekáváš.

K tvému dotazu o klíčích:
Ty jako člověk chápeš, že sloupec type rozlišuje, do které tabulky míří id, ale databázi to nevysvětlíš. Ta vyžaduje (pokud definuješ cizí klíč), že všechny hodnoty existují v odkázaném sloupci. Cizí klíč se ti tedy nepodaří vytvořit, tak jak chceš.
Nic ti ale nebude bránit provádět JOINy jak jsi zvyklý, jen vždy budeš muset mít podmínku na typ.
kozusnikjan
Profil *
Jo takhle. Já nad tímto problémem, jak to bude chápat databáze neuvažoval, protože nepoužívám propojení přes cizí klíče - vždycky mám v databázi id a podle nich to v mysql tahám přes podmínky. Jaká je výhoda přes cizí klíče, smím-li se zeptat?

Prezentaci si projedu, děkuji.
juriad
Profil
Cizi klíč slouží ke třem věcem:
- dokumentace pro uživatele s významem: tyto sloupce lze propojit.
- kontrola integrity dat v databázi: databáze ti nedovolí smazat záznam, na který vede odkaz.
- automatizace mazacích operací: když smažu uživatele, smaž vše, co se na uživatele váže.

Se samotným JOINem nemá nic společného.
kozusnikjan
Profil *
Aha. Takže i když použiji cizí klíče, tak pořád musím data tahat přes třeba takovýto dotaz? :
SELECT T.title, T.content, F.path, F.name FROM texts T, files F, map_files M 
WHERE M.file_id = F.id AND M.object_id = T.id AND M.object_table = texts
juriad
Profil
Ano. Ale k samotnému dotazu; od SQL92 je lepší použít přehlednější:

SELECT T.title, T.content, F.path, F.name
FROM texts T
JOIN map_files M ON M.object_id = T.id AND M.object_table = 'texts'
JOIN files F ON F.id = M.file_id
WHERE skutečná podmína na data, nikoli vazebná podmínka
kozusnikjan
Profil *
Aha. No nicméně JOIN lze použít i bez cizích klíčů, ne?
juriad
Profil
Ano lze. Důvody pro vytvoření cizího klíče jsou zmíněné v [#6].

K tomu mazání:
Představ si, že bys chtěl smazat text s id=1. K němu může být připojených 20 textů. Co s nimi? Pokud by existoval cizí klíč, buď by smazání nepovolil, nebo by naopak smazal záznam v mapovací tabulce (podle toho, jak ten klíč byl vytvořen; viz klauzule ON DELETE ...).
Zároveň takový klíč nepovolí změnu id textu, pokud k němu existuje nějaký text. (Nebo může přepsat i object_id v mapovací tabulce; viz klauzule ON UPDATE.)

Tedy docela dobře zabrání situaci, že se v databázi něco změní/smaže a stále by existovaly odkazy na původní hodnotu (která už neexistuje).
kozusnikjan
Profil *
Aha. Děkuji za informace :) Dost mi to pomohlo. Myslel jsem, že cizí klíče jsou zbytečnost a ony jsou vcelku dobrá vychytávka :)

Děkuji za vaše odpovědi a rady, díky kterým jsem své znalosti zase posunul o něco výše.

Vaše odpověď

Mohlo by se hodit


Prosím používejte diakritiku a interpunkci.

Ochrana proti spamu. Napište prosím číslo dvě-sta čtyřicet-sedm: