Връзките „едно към много“ са една от най-често срещаните връзки в базата данни. Ако искате да научите кога и как да използвате връзките един към много, тогава тази статия е чудесна отправна точка.
Със сигурност ще използвате връзки един към много, за да съхранявате информация във всяка релационна база данни, независимо дали проектирате софтуер на ниво предприятие или просто създавате проста база данни, за да следите колекцията от печати на чичо си.
Кратко въведение в релационния модел
Релационните бази данни са основен компонент на всяко модерно транзакционно приложение. Релационният модел се състои от таблици (данни, организирани в редове и колони), които имат поне един уникален ключ, който идентифицира всеки ред. Всяка таблица представлява обект. Това е показано в следния пример, много проста версия на таблица, представяща поръчки на клиенти:
Горната диаграма, която създадох онлайн с помощта на Vertabelo, има една таблица. Всеки ред в таблицата представлява една поръчка, а всяка колона (известна още като атрибут ) представлява всяка отделна информация, съдържаща се в поръчка.
За тези, които все още не са запознати с инструмента за проектиране на Vertabelo, статията Какви са символите, използвани в ER диаграмите? обяснява използваните символи и конвенции. Може също да искате да научите повече за релационни модели и бази данни, като използвате нашия курс за моделиране на бази данни.
Какво представляват връзките и защо имаме нужда от тях?
Ако погледнем по-задълбочено таблицата, използвана в предишния пример, ще видим, че тя всъщност не представлява пълен ред. Той не разполага с цялата информация, която бихте очаквали да има. Ще забележите, че не включва никакви данни, свързани с клиента, който е направил поръчката, нито има нещо за поръчаните продукти или услуги.
Какво трябва да направим, за да завършим този дизайн за съхраняване на данни за поръчки? Трябва ли да добавим информация за клиента и продукта към Поръчката маса? Това ще изисква добавяне на нови колони (атрибути) за имена на клиенти, данъчни идентификатори, адреси и т.н., както е показано по-долу:
"OrderID" | „Дата на поръчката“ | „OrderAmount“ | Клиент | „Адрес на клиента“ | „CustomerPhone“ | „TaxIdentifier“ |
---|---|---|---|---|---|---|
1 | 23 юни | $10 248,15 | International Services Ltd | 1247 St River Blvd, Шарлът, Северна Каролина | (555) 478-8741 | IS789456 |
2 | 27 юни | $14 785,45 | World Master Importing Inc. | 354 Mountain Hill Rd, Лос Анджелис, Калифорния | (555) 774-8888 | WM321456 |
3 | 01 юли | $7 975,00 | First State Provisioning Llc | 444 North Highway, Хюстън, Тексас | (555) 698-7411 | FS947561 |
4 | 03 юли | $6 784,25 | International Services Ltd | 1247 St River Blvd, Шарлът, Северна Каролина | (555) 478-8741 | IS789456 |
5 | юли-07 | $21 476,10 | World Master Importing Inc. | 354 Mountain Hill Rd, Лос Анджелис, Калифорния | (555) 774-8888 | WM321456 |
6 | 12 юли | $9 734,00 | First State Provisioning Llc | 444 North Highway, Хюстън, Тексас | (555) 698-7411 | FS947561 |
7 | 17 юли | $14 747,45 | World Master Importing Inc. | 354 Mountain Hill Rd, Лос Анджелис, Калифорния | (555) 774-8888 | WM321456 |
8 | 21 юли | $19 674,85 | International Services Ltd | 1247 St River Blvd, Шарлът, Северна Каролина | (555) 478-8741 | IS789456 |
Ако направим това, скоро ще срещнем проблеми. Повечето клиенти правят повече от една поръчка, така че тази система ще съхранява информация за клиентите много пъти, веднъж за всяка поръчка на всеки клиент. Това не изглежда като умен ход.
Освен това, какво се случва, когато клиент промени телефонния си номер? Ако някой трябва да се обади на клиента, той може да намери стария номер в предишни поръчки – освен ако някой не актуализира стотици (или дори хиляди) съществуващи поръчки с новата информация. Същото важи и за всяка друга промяна.
Релационният модел изисква от нас да дефинираме всеки обект като отделна таблица и да установим връзки между тях. Съхраняването на цялата информация в една таблица просто не работи.
Има няколко типа връзки между таблици, но вероятно най-често срещаната е връзката един към много, която често се записва като 1:N. Този вид връзка означава, че един ред в таблица (обикновено наричана родителска таблица) може да има връзка с много редове в друга таблица (обикновено наричана дъщерна таблица). Някои често срещани примери за връзки един към много са:
- Производител на автомобили произвежда много различни модели, но конкретен модел автомобил се произвежда само от един автомобилен производител.
- Един клиент може да направи няколко покупки, но всяка покупка се извършва от един клиент.
- Една компания може да има много телефонни номера, но един телефонен номер принадлежи на една компания.
Съществуват и други видове връзки между таблиците; ако искате да научите повече за тях, вижте тази статия за връзките много към много.
Връщайки се към нашия пример за първоначална поръчка, Customer
таблицата ще бъде родителската таблица и Order
маса на детето; клиент може да има много поръчки, докато една поръчка може да принадлежи на един клиент.
Моля, имайте предвид, че дефиницията „едно към много“ позволява ред в родителската таблица да бъде свързан с много редове във всяка дъщерна таблица, но не го изисква. Всъщност дизайнът позволява на клиента да има нулеви поръчки (т.е. нов клиент, който все още не е направил първата си покупка), една поръчка (относително нов клиент, който е направил една покупка) или много поръчки (чест клиент).
Показване на връзки „едно към много“ в диаграма на ER
Нека да разгледаме по-пълен пример за проста система за поръчки на клиенти, използвайки диаграма на ER (или взаимоотношения на обект). (Ако искате да научите повече за тези диаграми, Vertabelo Features:Logical Diagrams е чудесна отправна точка.) Ето модела:
Това е по-реалистичен дизайн. Ще забележите, че има нови обекти (таблици) в диаграмата, която вече съдържа таблиците Customer
, Order
, Order Detail
, и Product
. Най-важното обаче, което забелязвате, е, че вече имавръзки между масите .
В модел на база данни връзките са представени от линии, свързващи две единици. Характеристиките на тези връзки са представени от различни съединители:
- Когато има една вертикална линия, най-близкият до този конектор обект има само един ред, засегнат от връзката. Това е „едно“ в едно към много.
- Когато има многоредов съединител, който прилича на крак на врана, обектът, най-близък до този съединител, има множество реда, засегнати от връзката; това е „многото“.
Гледайки изображението и знаейки нотацията, лесно е да разберете, че диаграмата дефинира, че всяка Order
може да има много Order Detail
и че всеки Order Detail
принадлежи към една Order
.
Внедряване на връзка един към много между таблици
За да дефинира връзка едно към много между две таблици, дъщерната таблица трябва да препраща към ред в родителската таблица. Стъпките, необходими за дефинирането му, са:
- Добавете колона към дъщерната таблица, която ще съхранява стойността на основния идентификатор. (Всъщност повечето машини за бази данни позволяват това да бъде всеки уникален ключ от родителската таблица, а не само първичен ключ.) Колоната може да бъде дефинирана като задължителна в зависимост от нуждите на вашия бизнес; въпреки това обикновено се правят колони с външен ключ
Забележка: Добра практика е името на референтните колони да е същото като в реферираната (родителска) таблица. Това прави още по-лесно разбирането на връзката.
- Добавете външен ключ ограничение на дъщерната маса. Това показва, че всяка стойност, съхранена в тази нова колона, препраща към ред в родителската таблица.
Ограниченията за външния ключ са функция, налична в релационна база данни, която налага това:
- Когато добавите ред към дъщерната таблица, стойността на референтната колона трябва да съвпада с една (и само една) стойност в родителската таблица. (Ето защо колона или набор от колони, които съставляват първичен ключ или уникален ключ, трябва да бъдат посочени).
- Ако някой се опита да изтрие ред от родителската таблица или се опита да промени стойностите на уникалния/първичния ключ, използван като справка и има дъщерна таблица, която препраща към този ред, операцията ще се провали.
Тези две функции гарантират, че базата данни запазва своята цялост. Няма шанс за създаване на поръчки, отнасящи се до несъществуващ клиент, нито за изтриване на клиент, който вече има поръчки.
Създаване на външен ключ
Синтаксисът на външния ключ обикновено зависи от целевата база данни. След като дефинирате логическия си модел, можете да използвате функцията „Генериране на физически модел...“ на логическите диаграми на Vertabelo, за да трансформирате вашия (независим от базата данни) модел във физически модел, който съответства на вашия доставчик на база данни. Vertabelo също така ще генерира необходимия SQL скрипт, който ще ви позволи да създадете таблиците и връзките във вашата целева база данни.
Някои практически примери за 1:N отношения
Сега нека прегледаме някои примери за реални връзки един към много.
Връзка един към много, използваща първични ключове
Това е може би най-често срещаният сценарий при дефиниране на връзка един към много. Дъщерната таблица използва стойността на първичния ключ на родителската таблица, за да установи връзката.
Този пример описва основна онлайн услуга за стрийминг. Нека прегледаме какво се съхранява във всяка от таблиците и как те са свързани с другите таблици в нашия модел:
- Всеки
ServiceType
определя как се „държа“ един акаунт (например колко потребители могат да се свържат към системата едновременно, ако акаунтът има активиран Full HD и т.н.). Той има една връзка с други обекти:- Връзка един към много с
Account
, което означава, че всеки тип услуга може да има много акаунти от този тип.
- Връзка един към много с
- Всеки
Account
съхранява информация за един клиент. Той има две преки връзки с други обекти:- Всеки акаунт принадлежи към един
ServiceType
, както е обяснено по-горе. - Тази таблица има връзка едно към много с
Profile
таблица, което означава, че повече от един потребител могат да се свържат с нашата система, използвайки един и същ акаунт.
- Всеки акаунт принадлежи към един
- Всеки
Account
представлява потребител в нашата система. Той има две връзки с други обекти:- Всеки подпрофил принадлежи на един
Account
. Това позволява на всички членове на семейството (или може би група приятели) да споделят един и същ акаунт, докато всеки има свои лични атрибути (напр. име на потребителски профил). - Всеки профил има уникален
Avatar
.
- Всеки подпрофил принадлежи на един
- Всеки
Avatar
е изображение, което ни позволява бързо да идентифицираме всеки потребител на акаунт. Той има една връзка с друг обект:- Връзка един към много с
Profile
, което означава, че един аватар може да бъде присвоен на профили в различни акаунти.
- Връзка един към много с
Връзки един към много с естествени или сурогатни уникални ключове
Използването на сурогатни първични ключове е широко приет начин за моделиране на таблици. (Сурогатните първични ключове се генерират от базата данни и нямат действителна бизнес стойност.) Този метод произвежда ключове, които са по-лесни за използване и добавя известна гъвкавост, когато са необходими промени.
Има обаче ситуации – напр. когато трябва да взаимодействаме с външни системи – когато използването на ключ, генериран в нашата база данни, е лош подход. За тези сценарии обикновено е по-добре да използвате естествени ключове, които са уникални стойности, които са част от обекта, който се съхранява и не се генерира автоматично от нашата база данни.
Следващият пример представя основен модел на данни на организация, която следи превозните средства (т.е. марка, модел, цвят и година на автомобила), техните собственици и всички свързани нарушения на транзита. Когато го дефинирахме, използвахме сурогатни първични ключове, за да установим връзките между превозните средства и марките, моделите и собствениците, тъй като цялата тази информация се обработва вътрешно от нашата система.
В тази система как може полицай в друг град да съобщи за неправомерно паркирана кола, използвайки първичния ключ на нашето превозно средство (VehicleID
)? Такава информация естествено не е налична на паркираното превозно средство, но регистрационният номер е там. Това означава, че най-простият начин за получаване и свързване на информация от външен източник (в този пример всяко полицейско управление в страната) е чрез използване на естествен уникален ключ вместо сурогатен първичен ключ.
Физическата реализация на тази логическа диаграма за SQL Server е достъпна тук:
Връзки един към много на една и съща маса
Предишните примери се фокусираха върху връзките между две или повече таблици, но има и сценарии, при които връзката възниква между редове на една и съща таблица. Този вид връзка един към много се нарича още йерархична връзка; използва се в много системи за представяне на дървовидни структури, т.е. организационна схема, сметка в главната книга или продукт и неговите съставни части.
Първият път, когато трябва да създадете такъв вид структура, ще се изкушите да дефинирате таблица за всяко от нивата във вашата йерархия, както е показано на следната диаграма:
Има много проблеми при този подход:
- Всички таблици са почти идентични и съхраняват идентична информация.
- Ако вашата организация добави ново ниво, ще трябва да промените модела на данни и да добавите нова таблица, нови външни ключове и т.н.
- Ако служител получи повишение, трябва да го изтриете от една таблица и да ги вмъкнете в друга.
Следователно, най-добрият начин за моделиране на този вид структура е използването на една таблица, която се позовава на себе си, както е показано на тази диаграма:
Тук виждаме един единствен Employee
таблица и колона с име EmployeeID_Manager
. Тази колона препраща към друг служител в същата организация, който е ръководител/мениджър на текущия служител.
Добавих _Manager
суфикс за разграничаване между ID на текущия ред и ID на мениджъра. (Можем да използваме ManagerID
вместо това, но предпочитам да запазя оригиналното име на посочената колона и в случаите, когато и двете са в една и съща таблица, добавям суфикс, който обяснява ролята, която всъщност има).
Разбирането на йерархичните връзки е по-сложно от другите връзки един към много. Но ако забравите за таблицата, където се съхранява цялата информация, и си представите, че всъщност има различни таблици, всяка от които представлява ниво в йерархията, е малко по-лесно да се визуализира. Представете си, че правите връзката между две единици и след това ги комбинирате в един обект.
Какво следва?
Предоставените примери ще ви помогнат да идентифицирате различни сценарии, които изискват връзка един към много. Можете да започнете да проектирате своя собствена структура на база данни с помощта на Vertabelo Database Modeler, уеб-базиран инструмент, който ви позволява не само да генерирате логически модел, но и да създадете физическа версия на него за доставчика на база данни, от който се нуждаете.
Сега е ваш ред – използвайте секцията за коментари, за да ни кажете какво мислите за тази статия, задайте допълнителни въпроси или споделете своя опит в моделирането на база данни.