Prepojenie tabuliek v databáze
Po niekoľkých prednáškach o objektovo orientovanom programovaní si už dáme s OOP pokoj. Ukázali sme si základné použitie v praxi a to nám nateraz stačí. Vieme, čo to je, na čo to slúži a ako to funguje, ten základ už vieme. Tieto prednášky boli v istých momentoch skôr teoretické ako praktické, resp. sme počas nich nevytvorili a nenaučili sa nič nové v súvislosti s našou stránkou. Aby to nebolo nudné a demotivujúce, prejdeme si pre zmenu niečo nové z jazyka SQL:)
Vráťme sa do čias, kedy sme si vytvárali v databáze tabuľku users (zapnite si aj phpMyAdmin). Ako vieme, táto tabuľka slúži na ukladanie používateľov. Každý používateľ predstavuje jeden riadok v tejto tabuľke a každý stĺpec predstavuje jednu konkrétnu informáciu o danom používateľovi. Štuktúra tejto tabuľky je akousi základnou štuktúrou pre hlavnú tabuľku dát nejakej konkrétnej kategórie, v tomto prípade je to základná tabuľka pre používateľov. Obsahuje najdôležitejší stĺpec id, ktorý predstavuje unikátny identifikátor pre usera, je to akokeby jeho ID, ktoré ho v systéme charakterizuje.
Ak by sme chceli o používateľoch uchovávať (štandardne to tak v praxi býva) viacero informácii ako napríklad bydlisko (ulica, číslo, mesto, psč), dátum narodenia a podobne, asi by ste v tomto prípade len pridávali stĺpce do tejto tabuľky a do nej ukladali hodnoty. Ak by sme ale mali takýchto údajov príliš veľa, nebolo by veľmi optimálne mať v tabuľke napríklad 40 stĺpcov, kde by každý vravel o niešom v súvislosti s používateľom. Jednak by to bolo neprehľadné a na druhej strane by pri selectoch a where podmienkach troška spomaľovalo komunikáciu s DB, resp. pri selectoch by sa zbytočne vyberalo veľa dát atď.
Riešenie na toto je mať v databáze viacero tabuliek, ktoré sa týkajú tej istej skupiny dát – v našom prípade používateľov. V praxi sa zvykne tieto spoločné tabuľky nazývať nejakým spoločným prefixom (slovo na začiatku), aby bolo hneď jasné, že tabuľky súvisia, resp. že dáta v nich sú spoločné. Ideálne by bolo, aby sme teda mali napríklad tabuľku users (základnú), následne napríklad tabuľku user_address (tam by sa ukladali adresy používateľov), user_contact_info (telefóny, maily, sociálne siete...), user_education (informácie o štúdiu používateľov), user_photo (fotky používateľov) a podobne.
Dotazy na databázu (na dáta) sú väčšinou konkrétne. To znamená, že málokedy potrebujeme v kóde vytiahnuť úplne všetky dáta o danom používateľovi (zo všetkých tabuliek). Aj keď si niekedy meníte profil na nejakej stránke, často býva rozdelený na viacej častí a nie je všetko na jednej stránke. To je presne moment, ak ste napríklad v sekcii contact information (kontaktné údaje), kedy sa načítavajú dáta o používateľovi len z konkrétnych tabuliek na to určených a nie je nutné načítavať z jednej, kde je všetko alebo zo všetkých. Toto je jeden dôvod, prečo je dobré dáta rozumne rozdeľovať do viacerých tabuliek. V súvislosti s prehľadnosťou a efektivitou selectov a podobne je za tým troška viac teórie, čo a ako správne rozdeliť, nad tým sa ale nateraz nejdeme pozastavovať.
Druhý dôvod, prečo je dobré (alebo skôr nutné) mať viacero tabuliek pre istú spoločnú skupinu dát, má niečo spoločné s tým, že v tejto tabuľke nám jeden riadok predstavuje práve jedného používateľa a hodnota v stĺpci práve jednu hodnotu o danom userovi. Nateraz nám to stačilo, jeden používateľ by mal mať iba jedno meno, priezvisko, rolu alebo počet rokov. Čo však ale v prípade, kedy potrebujeme o jednom používateľovi uchovávať nejakú informáciu viac krát?
Tento prípad sa zvykne popisovať troška matematicky a to tak, že je nutné vedieť, aký počet daných údajov je nutné v systéme uchovávať. Ak bude dané, že používateľ môže mať iba jedno meno, znamená to, že maximálny počet tohto údaju bude 1. To znamená, že ak počet používateľov bude 200 (premenná x bude reprezentovať počet používateľov, tak x=200), tak aj počet mien bude 200 (200x1). To značí, že pre tento údaj nám treba toľko riadkov, koľko bude používateľov, takže môže byť tento údaj ukladaný do tejto tabuľky. Podobne je to aj v prípade priezviska, veku a role.
Ak by chceli napríklad ukladať mail používateľa, nemusí to byť iba jeden mail. Povedzme, že by systém povoloval používateľovi uložiť 3 maily. Tým pádom je počet mailov používateľa rovný 1-3. Pri maximálne vyplnených dátach by počet mailov v tabuľke bol 3x (tri krát počet všetkých používateľov). Nebojte sa, toto matematické vyjadrenie nie je nejak dôležité, je to len na porovnanie. Tento problém by sme ešte vedeli zvládnuť, vytvorili by sme si aj v tejto istej tabuľke (users) stĺpce mail_1, mail_2 a mail_3, ktoré by v prípade nutnosti obsahovali hodnoty a v opačnom by boli prázdne (null).
Problém ale nastáva v prípade, že by sme v systéme potrebovali uchovávať nejakú informáciu, ktorej počet nie je obmedzený. Mohli by to byť napríklad fotografie, komentáre alebo telefónne čísla. Práve posledne menovaný prípad si rozoberieme. Úloha je jasná, náš systém uchováva info o useroch a chceme, aby každý používateľ mohol zadať ľubovoľný počet telefónnych čísiel. To znamená, že ich môže byť 0, 1, 3, 50, 200. Tento prípad sa označuje, že ich môže byť 1 až N, kde písmeno N (premenná) predstavuje ľubovoľné číslo až po nekonečno. Otázka znie, ako spraviť štruktúru v databáze, aby sme toto mohli ukladať.
Ak by sme to chceli ukladať do jednej tabuľky users, bolo by to v podstate nemožné. Ak vieme, že v jednom stĺpci máme jednu hodnoty, ako by sme spravili stĺpce? Bolo by nemožné vytvárať stĺpce typu phone_number_1, phone_number_2, phone_number_3, …, phone_number_50, …, phone_number_200 atď. Presne v tomto prípade by sme vytvorili tabuľku, ktorá by slúžila iba na ukladanie telefónnych čísiel. Ako by ale vyzerala štruktúra tejto tabuľky?
V tomto prípade by sa zmenila podstata tabuľky vzhľadom k informácii o používateľovi. V tabuľke users je jeden riadok rovný jednému používateľovi, žiadne dva riadky nie sú rovnaké, resp. žiadne dva riadky nehovoria o tom istom používateľovi. Táto nová tabuľka bude slúžiť na uchovávanie telefónnych čisiel, takže jej hlavný popis bude, že jeden riadok v tejto tabuľke bude predstavovať jedno telefónne číslo. V tomto prípade má táto tabuľka vzhľadom k hlavným dátam (používateľom) taký vzťah, že viacero riadkov v tejto tabuľke (1 až N riadkov) môže súvisieť s jedným používateľom. Toto je na tom najdôležitejšie, pretože je to vlastne akési také pravidlo. Ak máme rôzne informácie o nejakom konkrétnom objekte (user), ktorých počet je malý (1, 2 alebo 3), môže to byť v tabuľke, kde jeden riadok predstavuje jeden hlavný objekt. V prípade ale, že nejakých informácii môže byť nekonečne veľa (1-N), treba na to novú tabuľku.
Ako sme povedali, v tejto tabuľke bude jeden riadok predstavovať jedno telefónne číslo a viacero riadkov môže súvisieť s jedným používateľom. Ak by sme dali tabuľky vedľa seba a spojili napríklad riadok používateľa s riadkami v tabuľke user_phone_number, ktoré s ním súvisia, graficky by to vyzeralo ako také rozšírenie údajov o používateľovi – každý jeden by mal v druhej tabuľke viacero svojich údajov = riadkov = telefónnych čísel. Najdôležitejšia vec na takejto štruktúre, resp. posobe, kde dve tabuľky navzájom súvisia (ich údaje) je zabezpečiť prepojenie dát.
Prepojením v tomto prípade myslíme akési uchovanie a zabezpečenie informácie, aby sa vedelo, ktorý riadok z tabuľky telefónov súvisí s ktorým riadkom v hlavnej tabuľke. Ľudovo povedané, aby sme vedeli, ktoré čísla patria ku konkrétnemu používateľovi. Asi tušíte, ako sa to asi zvykne robiť a ak ste si mysleli, že práve pomocou id v tabuľke users, tak máte pravdu. V takýchto tabuľkách, dali by sa nazvať ako vedľajšie tabuľky nejakého dátového objektu (user), zvyknú byť prvé dva stĺpce nasledovné. Prvým je id ako v každej inej tabuľke, v tomto prípade to ale bude id nie používateľa, ale telefónneho čísla a práve druhý stĺpec slúži na uchovanie prepojenia. V tomto prípade by bol druhý stĺpec s názvom id_user, v ktorom by bol uložený práve údaj z tabuľky users zo stĺpca id. Takto bude jasné, ktoré číslo ku komu patrí.
Na záver tejto prednášky si poďme túto tabuľku aspoň vytvoriť a v nasledujúcej si ukážeme prácu s dvomi tabuľkami naraz. Naša tabuľka by mohla v jednoduchej verzii obsahovať iba tri stĺpce, okrem idčiek samotné telefónne číslo (to by sa dalo rozdeliť na viac stĺpcov ako typ – mobil/pracovný a podobne alebo na prevoľbu a hlavnú časť, nejdeme to ale zbytočne teraz komplikovať). Príkaz SQL na vytvorenie takjeto tabuľky by mohol vyzerať nasledovne (v SQL sekcii v systéme phpMyAdmin nad našou databázou zapr_db_1):
CREATE TABLE user_phone_numbers (
id BIGINT UNIQUE AUTO_INCREMENT,
id_user BIGINT,
phone_number VARCHAR(50)
);
Po vykonaní tejto query sa nám v našej databáze vytvorí nová tabuľka, takže teraz už bude naša databáza obsahovať dve tabuľky. Už len podľa ich názvu je jasné, že aký druh dát uchovávajú tieto tabuľky. Aby sme s týmito tabuľkami mohli pracovať, mali by sme novovytvorenú naplniť dátami, urobíme tak ale na začiatku ďalšej prednášky.