Symetrické vazby
Pokud chceme sledovat vazby mezi položkami stejné tabulky (např. podobné výrobky), nejspíš za tím účelem vytvoříme dvousloupcovou tabulku vyrobky_podobne (vyrobek, podobny)
, kde oba sloupce budou směřovat na primární klíč hlavní tabulky. Vazba nemusí být symetrická, v tom případě se s tabulkou pracuje jako s běžnou vazební tabulkou a faktu, že oba sloupce ukazují do stejné tabulky, si nemusíme všímat.
Pokud má však být vazba symetrická (takže když je jeden výrobek podobný druhému, tak je také druhý podobný prvnímu), je zbytečné ukládat do tabulky obě vazby. Tento přístup ale zkomplikuje všechny dotazy do tabulky – místo vyrobek = @id
musíme psát @id IN (vyrobek, podobny)
, při vypisování nebo spojování s dalšími tabulkami se to zkomplikuje o nutnost zjišťovat, jestli je vazba ve sloupci vyrobek
nebo podobny
.
Jak z toho ven? Řešení je překvapivě jednoduché. Stačí nadefinovat pohled:
CREATE VIEW vyrobky_podobne_vsechny AS SELECT vyrobek, podobny FROM vyrobky_podobne UNION SELECT podobny, vyrobek FROM vyrobky_podobne
Data potom můžeme vybírat z tohoto pohledu, mazat je ze základní tabulky pomocí zmíněného @id IN (vyrobek, podobny)
a vkládat obvyklým způsobem.
Někdo data organizuje tak, aby v jednom sloupci byla vždy menší hodnota než ve druhém, při vytvoření pohledu to je ale zbytečná práce navíc díky čemuž se nemůže stát, že by v tabulce byla stejná vazba dvakrát. Pohled nám tyto řádky sice sjednotí do jednoho, ovšem pouze za předpokladu, že v tabulce není další sloupec s různou hodnotou v jednotlivých řádcích. Pro zajištění konzistence tedy můžeme použít trigger:
CREATE TRIGGER vyrobky_podobne_bi BEFORE INSERT ON vyrobky_podobne FOR EACH ROW SET @vyrobek = NEW.vyrobek, NEW.vyrobek = LEAST(@vyrobek, NEW.podobny), NEW.podobny = GREATEST(@vyrobek, NEW.podobny); CREATE TRIGGER vyrobky_podobne_bu BEFORE UPDATE ON vyrobky_podobne FOR EACH ROW SET @vyrobek = NEW.vyrobek, NEW.vyrobek = LEAST(@vyrobek, NEW.podobny), NEW.podobny = GREATEST(@vyrobek, NEW.podobny);
Přijďte si o tomto tématu popovídat na školení Návrh a používání MySQL databáze.
Diskuse
SiseL:
dobre mienena rada!
rmaslo:
Stejný princip se hodí když evidujeme třeba nějaký zápasy a pak z nich dělame nějaký statistiky a zápas chceme zadavat jenom jednou...Prostě přes union si definujeme view pomocí kterýho uděláme snadno ze záznamu
Česko|Rusko|5|0
záznamy
Česko|Rusko|5|0
Rusko|Česko|0|5
Pak se třeba počet vstřelených a inkasovaných gólů přes tým počítá poměrně snadno
Ondrej Ivanic:
Zaujimave a pekne riesenieAle aj tak by som asi vkladal radsej dva riadky. Zaujimala by ma vykonnost takehoto riesenia, ci to vobec stoji za to. S MySQL 5 som skoro vobec nerobil a tak neviem posudit...
Jakub Vrána
:
S vkládáním dvou řádek je problém ten, že může vzniknout nekonzistence.
Výkonnosti bych se nebál, UNION se optimalizuje výtečně.


RATMex B:
Ako môže vzniknúť u dvojitého vkladania nekonzistencia keď niekto nevloží prepísaným spôsobom, tak môže vzniknúť nekonzistencia aj u UNION-u, pokiaľ niekto nebude mazať predpísaným spôsobom.Spoločným menovateľom oboch kritických bodov je zmena záznamov a nie výber, preto by bolo lepšie tento problém riešiť na úrovni triggerov. Do tabuľky vkladať a mazať ako z "jednozáznamovej", triggery by z nej robili fyzicky dvojzáznamovú. Výber by prebiehal normálne.
Jakub Vrána
:
Nikoliv, mazáním nekonzistence vzniknout nemůže - buď tam jsou oba záznamy nebo žádný.
Zajistit fyzické vložení záznamu pomocí triggeru je také dobré řešení.


Diskuse je zrušena z důvodu spamu.

