Указания: Нека имаме да проектираме фрагмент от база данни за приложение, обслужващо административно отдели и хора, които работят в различните отдели. За сега разглеждаме тази част от персонала, които са ИТ- програмисти и QA-и. За програмистите се пази дали са front end, back end или са full stack, както и на кои езици програмират – един или повече от предварително дефинирани езици. A за QA-ите се пази дали са manual или automation.
Така би изглеждала евентуалната ER -диаграма:
Нека да определим обектите в нея:
- отдели
- хора
- програмисти
- QA
Програмистите и QA-те са подкласове обекти на хората. Причината е, че и двата типа носят характерните черти на всички хора, но добавят и свои характеристики като езици за програмиране, тип тестване и тн.
Нека да определим връзките:
- отдели – хора (1:М )
- хора– програмисти (1:1)
- хора– QA–s (1:1)
В нашия случай последните две връзки от тип isA са 1:1. Причината е, че точно един обект от таблицата хора можем да го направим точно един път програмист или QA. Не е възможно той да заема повече от една длъжност на програмист или на QA.
Интересно е в условието, че програмистите могат да знаят повече от един езици за програмиране, които хем са предварително дефинирани (тоест не са случайни), хем могат и да се разширяват (в света ежедневно се появяват нови езици за програмиране).
Първи вариант: Първа възможност е езиците да си останат атрибут на таблцата програмисти и да бъдат от тип SET – тогава може да се избере повече от един език за един програмист – както е по условие. Това обаче налага друго нещо – множеството на езиците не е ограничено, както споменахме, така че какво ще коства това в бъдеще? Да предефинираме колоната чрез ALTER TABLE е DDL – тоест промяна по схемата. Да не говорим, че изобщо няма да ни позволи да променим SET при положение. че вътре вече има попълнени стойности, а ние изпуснем някои от старите. Затова отпада като вариант.
Втори вариант: varchar – вариант, който в случая не е удовлетворява условието – в тази колона ще може да си пишем каквото си искаме и никой няма да разбере че сме сгрешили, а в условието пише – “предварително зададени”. При други случаи щеше да е чудесно и бързо решение, но в случая го изоставяме.
Трети вариант: Остава вариантът да ползваме някаква номенклатурна таблица с езици. Ако се наложи да се добави даден език – няма проблем – това е просто един insert, което е DML- тоест всичко е наред и за в бъдеще. Имайки предвид условието – това е най-подходящо решение. Връзката между програмисти и езици ще бъде M:M. Така че ще ни трябва и свързваща таблица. Променяме диаграмата така:
Да създадем базата:
DROP DATABASE IF EXISTS emp_depts; CREATE DATABASE emp_depts; USE emp_depts; CREATE TABLE `departments` ( `id` int AUTO_INCREMENT, `name` varchar(255) NOT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB; CREATE TABLE `person` ( `id` INT AUTO_INCREMENT, `name` varchar(255) NOT NULL, `egn` varchar(10) NOT NULL UNIQUE , `departmentID` INT DEFAULT NULL, PRIMARY KEY (`id`), CONSTRAINT FOREIGN KEY (`departmentID`) REFERENCES `departments` (`id`) ) ENGINE=InnoDB; CREATE TABLE `programmers` ( `person_id` INT AUTO_INCREMENT PRIMARY KEY, `front_back_end` ENUM('FRONT_END','BACK_END','FULL_STACK') NULL, CONSTRAINT FOREIGN KEY (`person_id`) REFERENCES `person` (`id`) ) ENGINE=InnoDB; CREATE TABLE `qas` ( `person_id` INT AUTO_INCREMENT PRIMARY KEY , `isAutomation` BIT(1) DEFAULT NULL, CONSTRAINT FOREIGN KEY (`person_id`) REFERENCES `person` (`id`) ) ENGINE=InnoDB; CREATE TABLE languages( `id` INT auto_increment PRIMARY KEY, `name` VARCHAR(100) NOT NULL ) ENGINE=InnoDB; CREATE TABLE programmer_language( `programmer_id` INT NOT NULL, `language_id` INT NOT NULL, primary key(`programmer_id`,`language_id`), CONSTRAINT FOREIGN KEY(`programmer_id`) REFERENCES `programmers`(`person_id`), CONSTRAINT FOREIGN KEY(`language_id`) REFERENCES `languages`(`id`) ) ENGINE=InnoDB;
Даниел Джолев
В една от предните статии пише, че връзка 1:1 се реализира с ограничение UNIQUE на външния ключ, но тук(както и в базата за спортните групи и треньорите) не видях да има такова ограничение при връзката 1:1. Може ли да разясните как стоят нещата ?
Здравей, Дидо,
Да, така се реализира връзката. В случая тя е между Person -> Programmers и Person -> Qas. И в Programmers, и в Qas има външен ключ към таблицата Person: `person_id` INT AUTO_INCREMENT PRIMARY KEY. Както виждате, person_id е първичен ключ, следователно е едновременно not null + unique. И така правилото, което цитираш по-горе, е реализирано.