Autor Zpráva
Acer1968
Profil
Dobrý den všem.

Jsem začátečník. Proto se možná zeptám blbě a proto možná očekávám odpověď "po lopatě", pokud tu bude někdo, kdo na to bude mít náladu. Mám takhle navrženou databázi:

Obrázek je zde http://duotech.9e.cz/images/relace_databaze.png

Jde mi o tu část v červeném rámečku. Tabulka duo_kontakty_zakazniku mi spojuje tabulku duo_zakaznici s tabulkou duo_kontakty tak, že platí:
1) každý kontakt může být přiřazen právě jednomu zákazníkovi (prostě nikdo z kontaktů nedělá ve více firmách současně a pokud ano, je to jiný kontakt)
2) každý zákazník může mít přiřazeno libovolně mnoho kontaktů (prostě v oddělení zákazníka pracuje víc lidí, kteří mohou objednávat)

Je to tak?

Pak u tabulky duo_zakazky by mělo platit:
1) každá zakázka má přiřazeného právě jednoho zákazníka (není možné v jedné zakázce vyrábět pro víc zákazníků najednou)
2) každá zakázka má přiřazen právě jeden kontakt od toho zákazníka (prostě někoho z toho nákupnho oddělení zákazníka, kdo tu zakázku objednal)

A teď bych potřeboval docílit toho, abych, když v nové zakázce v tabulce duo_zakazky vyberu zákazníka z nějakého rozbalovacího menu (prostě zákazník i jeho kontakty musejí být v databázi dřív, než založím novou zakázku), jsem mohl vybrat z druhého rozbalovacího menu jen z těch kontaktů, které jsou příslušné tomu konkrétnímu zákazníkovi. Dá se to nějak vynutit v MySQL a pomocí "nějakého" jednoho dotazu? Nebo prostě musím v PHP napřed naplnit rozbalovací menu pro výběr zákazníka a teprve na základě téhle volby naplnit rozbalovací menu pro výběr patřičného kontaktu?

Ono to vynucování asi nechápu. Já myslel, že když budu ručně editovat tu tabulku duo_zakazky v poli ID_zakaznika a pak do pole ID_kontaktu vložím kontakt, který není svázán s tím zákazníkem, že to databáze pozná a zařve chybu. Ale ono ne. Tak, jak to mám udělané, mohu do zakázky vesele strkat zákazníka i kontakt, které spolu nesouvisí. Já chápu, že si to pak ošetřím skriptem, ale myslel jsem, že právě cizí klíče slouží k nějaké kontrole integrity a tohle bych za integritní požadavek považoval. Takhle to vypadá, že databáze zařve jen tehdy, když zadám hodnotu, která v tabulkách duo_zákaznici nebo duo_kontakty není vůbec, ale na té spojové tabulce vůbec nezáleží.

Kde dělám chybu v uvažování?

SQL dotaz na výpis seznamu zakázek včetně zákazníka a jeho kontaktu jsem spáchal:
select zak.nase_cislo_zakazky as "Číslo zakázky", kli.nazev as "Zákazník", kon.prijmeni as "Kontaktní osoba"
from duo_zakazky as zak
left join duo_zakaznici as kli on zak.ID_zakaznika=kli.ID_zakaznika
left join duo_kontakty as kon on zak.ID_kontaktu=kon.ID_kontaktu

Teď jen přemýšlím, jestli jsem tu tabulku duo_kontakty_zakazniku neudělal úplně zbytečně, ale podle mě ne.

Prosím tedy někoho, kdo tomu rozumí víc než já, aby mi když tak napsal, jestli vůbec ten návrh a rozbití tabulek na menší je správně a má smysl.

Děkuji.

Petr Vavřinec
Kajman
Profil
1. Udělejte v tabulce duo_kontakty_zakazniku primární klíč na kombinaci obou sloupců.
2. Udělejte v tabulce duo_zakazky cizí klíč na kombinaci sloupců ID_zakaznika a ID_zakaznika do tabulky duo_kontakty_zakazniku.
Acer1968
Profil
Kajman:
ad 1) Tak ta neexistence PK v té spojové tabulce mne samozřejmě dráždila, akorát jsem včera kvůli tomu četl opět knížky. Mě vždy unikal smysl vícesloupcových PK, ale tady ho konečně díky Vám zřetelně vidím.
ad 2) Jsa „odkojen“ MS Accessem, relace jsem zvyklý navrhovat vizuálně. Proto i ten diagram z Workbenche. Ale udělat CK přes dva sloupce snad nebude o nic těžší, než přes jeden.

A pak v tom PHP kódu pro zadání zakázky byste naplnil jednu roletu k výběru kontaktu a zákazníka současně tou kombinací? Nebo dvě rolety, kdy ta druhá s kontakty se naplní až po výběru zákazníka?
Kajman
Profil
Optimální řešení závisí na mohutnosti tabulek. Často se k zjednodušení používá javascript, který může hlídat závislosti (předem připravené, nebo zjištěné přes ajax) či vytvářen autocomplement (při počtu, kdy jsou klasické select boxy nepoužitelné).

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:

0