Miks on halb mõte kasutada erinevates tabelites ühesuguse nimega (id, kood või code) primaarvõtme veergu?

Postitas Erki Eessaar 16.02.2023 15:43 (muudeti 06.02.2024 20:57)
See muudab keerulisemaks tabelites olevatest andmetest arusaamise ja tabelite põhjal päringute tegemise.

Sellise nimega primaarvõtme veerud on üks sümptom, mis viitab sellele, et andmebaasi disainis esineb "Üks suurus kõigile" andmebaasi disaini antimuster. Antimuster on struktuurse kirjutamise viis, kuidas panna kirja halbu lahendusi levinud probleemidele.

Selline nimi on liiga üldine ja tuleb päringute tulemuses enamasti ümber nimetada. Vastasel juhul tekib päringu tulemusse mitu sama nimega veergu, mis vormiliselt on küll SQLis lubatud, kuid sisuliselt muudab see päringu tulemuse raskesti kasutatavaks.

Oletame, et andmebaasis on tabelid:

Mark (id, nimetus)
Primaarvõti (id)

Auto (id, mark_id, registri_nr)
Primaarvõti (id)
Välisvõti (mark_id) Viitab Mark (id)

Kui ülesandeks on leida iga auto kohta margi identifikaator, nimetus, auto identifikaator ja registri number, siis tuleks kirjutada päring

SELECT Mark.id AS mark_id, nimetus, Auto.id AS auto_id, registri_nr
FROM Mark INNER JOIN Auto ON Mark.id=Auto.mark_id;

Samas, kui andmebaasis oleksid tabelid:

Mark (mark_id, nimetus)
Primaarvõti (mark_id)

Auto (auto_id, mark_id, registri_nr)
Primaarvõti (auto_id)
Välisvõti (mark_id) Viitab Mark (mark_id)

, siis saab selle ülesande lahendada SQL standardit hästi järgivas andmebaasisüsteemis (nt PostgreSQL) oluliselt lühema lausega. USING võimaldab teha ühendamist üle samanimeliste veergude. Ühendamise tulemuses on see veerg (antud juhul mark_id) ühekordselt, st SELECT klauslis pole veeru nime ees vaja täpsustada tabeli nime.

SELECT mark_id, nimetus, auto_id, registri_nr
FROM Mark INNER JOIN Auto USING (mark_id);

Veel üks, veidi pikem näide, kus koodi kirjutamise mugavus tuleb paremini välja. Leia ilma kordusteta milliseid kaupu on millised kliendid ostnud.

SELECT DISTINCT klient.id AS klient_id, klient.perenimi, kaup.id AS kaup_id, kaup.nimetus AS kauba_nimetus
FROM Klient INNER JOIN Tellimus ON Klient.id=Tellimus.klient_id
INNER JOIN Tellimuse_rida ON Tellimus.id=Tellimuse_rida.tellimus_id
INNER JOIN Kaup ON Tellimuse_rida.kaup_id=Kaup.id;

Tuleb olla tähelepanelik, et mitte valesid veerge kokku ühendada (tegin ka ise selle vea seda näidet kirjutades).

vs.

SELECT DISTINCT klient_id, klient.perenimi, kaup_id, kaup.nimetus AS kauba_nimetus
FROM Klient INNER JOIN Tellimus USING (klient_id)
INNER JOIN Tellimuse_rida USING (tellimus_id)
INNER JOIN Kaup USING (kaup_id);

Vastukaaluks saab öelda, et võtmeveeru nimi id võib lihtsustada mingites rakenduse ehitamise vahendites andmebaasi kasutuse realiseerimist. Lõppkokkuvõttes, nagu väga sageli (andmebaasi) tehnilise lahenduse loomise juures, on kõik valikute küsimus ning igal valikul on oma head ja halvad tagajärjed.

Hinda postitust:

Keskmine hinne : 5.0