sql >> Database >  >> RDS >> Database

Wat is een één-op-veel-relatie in een database? Een uitleg met voorbeelden

Een-op-veel-relaties zijn een van de meest voorkomende databaserelaties. Als je wilt leren wanneer en hoe je een-op-veel-relaties kunt gebruiken, dan is dit artikel een goed startpunt.

U zult zeker een-op-veel-relaties gebruiken om informatie op te slaan in een relationele database, of u nu software op ondernemingsniveau ontwerpt of gewoon een eenvoudige database maakt om de postzegelverzameling van uw oom bij te houden.

Een korte introductie tot het relationele model

Relationele databases vormen een kerncomponent van elke moderne transactionele applicatie. Het relationele model bestaat uit tabellen (gegevens georganiseerd in rijen en kolommen) die ten minste één unieke sleutel hebben die elke rij identificeert. Elke tabel vertegenwoordigt een entiteit. Dit wordt getoond in het volgende voorbeeld, een zeer eenvoudige versie van een tabel die klantorders weergeeft:

Het bovenstaande diagram, dat ik online heb gemaakt met Vertabelo, heeft een enkele tabel. Elke rij in de tabel vertegenwoordigt één volgorde en elke kolom (ook bekend als een attribuut ) staat voor elk afzonderlijk stukje informatie in een bestelling.

Voor degenen die nog niet bekend zijn met de Vertabelo-ontwerptool, het artikel Wat zijn de symbolen die worden gebruikt in ER-diagrammen? verklaart de gebruikte symbolen en conventies. Misschien wilt u ook meer leren over relationele modellen en databases met behulp van onze cursus databasemodellering.

Wat zijn relaties en waarom hebben we ze nodig?

Als we dieper ingaan op de tabel die in het vorige voorbeeld is gebruikt, zullen we zien dat deze niet echt een volledige bestelling vertegenwoordigt. Het bevat niet alle informatie die je zou verwachten. U zult merken dat het geen gegevens bevat met betrekking tot de klant die de bestelling heeft geplaatst, en ook niets over de bestelde producten of diensten.

Wat moeten we doen om dit ontwerp voor het opslaan van bestelgegevens te voltooien? Moeten we klant- en productinformatie toevoegen aan de Bestelling tafel? Dat vereist het toevoegen van nieuwe kolommen (attributen) voor klantnamen, belasting-ID's, adressen, enz., zoals hieronder weergegeven:

"OrderID" "Besteldatum" "Orderbedrag" Klant "Klantadres" "Telefoon klant" "TaxIdentifier"
1 23 juni $10 248,15 International Services Ltd 1247 St River Blvd, Charlotte, NC (555) 478-8741 IS789456
2 27 juni $14 785,45 World Master Importing Inc. 354 Mountain Hill Rd, Los Angeles, CA (555) 774-8888 WM321456
3 01 juli $7 975,00 First State Provisioning LLC 444 North Highway, Houston, TX (555) 698-7411 FS947561
4 jul-03 $6 784,25 International Services Ltd 1247 St River Blvd, Charlotte, NC (555) 478-8741 IS789456
5 jul-07 $21 476,10 World Master Importing Inc. 354 Mountain Hill Rd, Los Angeles, CA (555) 774-8888 WM321456
6 -12 juli $9 734,00 First State Provisioning LLC 444 North Highway, Houston, TX (555) 698-7411 FS947561
7 17 juli $14 747,45 World Master Importing Inc. 354 Mountain Hill Rd, Los Angeles, CA (555) 774-8888 WM321456
8 21 jul $19 674,85 International Services Ltd 1247 St River Blvd, Charlotte, NC (555) 478-8741 IS789456

Als we dat doen, komen we al snel in de problemen. De meeste klanten plaatsen meer dan één bestelling, dus dit systeem zal klantinformatie vele malen opslaan, één keer voor elke bestelling van elke klant. Dat lijkt me geen slimme zet.

Wat gebeurt er bovendien als een klant zijn telefoonnummer wijzigt? Als iemand de klant moet bellen, kan deze het oude nummer bij eerdere bestellingen vinden, tenzij iemand honderden (of zelfs duizenden) bestaande bestellingen bijwerkt met de nieuwe informatie. En hetzelfde geldt voor elke andere wijziging.

Een relationeel model vereist dat we elke entiteit definiëren als een afzonderlijke tabel en relaties tussen hen leggen. Alle informatie in één tabel opslaan werkt gewoon niet.

Er zijn verschillende soorten relaties tussen tabellen, maar waarschijnlijk de meest voorkomende is de een-op-veel-relatie, die vaak wordt geschreven als 1:N. Dit soort relatie betekent dat één rij in een tabel (meestal de bovenliggende tabel genoemd) een relatie kan hebben met veel rijen in een andere tabel (meestal onderliggende tabel genoemd). Enkele veelvoorkomende voorbeelden van een-op-veel-relaties zijn:

  • Een autofabrikant maakt veel verschillende modellen, maar een bepaald automodel wordt maar door één autofabrikant gebouwd.
  • Eén klant kan meerdere aankopen doen, maar elke aankoop wordt gedaan door één klant.
  • Eén bedrijf kan veel telefoonnummers hebben, maar een telefoonnummer hoort bij één bedrijf.

Er zijn ook andere soorten relaties tussen tabellen; als je er meer over wilt weten, bekijk dan dit artikel over veel-op-veel-relaties.

Terugkomend op ons eerste bestelvoorbeeld, de Customer tabel zou de bovenliggende tabel zijn en de Order tafel het kind; een klant kan veel bestellingen hebben, terwijl een bestelling aan één klant kan toebehoren.

Houd er rekening mee dat de een-op-veel-definitie het mogelijk maakt dat een rij in de bovenliggende tabel wordt gekoppeld aan veel rijen op elke onderliggende tabel, maar dit is niet vereist. In feite stelt het ontwerp een klant in staat om nul bestellingen te hebben (d.w.z. een nieuwe klant die zijn eerste aankoop nog niet heeft gedaan), één bestelling (een relatief nieuwe klant die een enkele aankoop heeft gedaan) of veel bestellingen (een frequente klant).

Een-op-veel-relaties weergeven in een ER-diagram

Laten we eens kijken naar een vollediger voorbeeld van een eenvoudig klantbestelsysteem met behulp van een ER-diagram (of entiteitsrelatie). (Als u meer wilt weten over deze diagrammen, is Vertabelo-functies:logische diagrammen een goed startpunt.) Dit is het model:

Dit is een realistischer ontwerp. U zult zien dat er nieuwe entiteiten (tabellen) in het diagram staan, dat nu de tabellen Customer bevat. , Order , Order Detail , en Product . Het belangrijkste dat echter opvalt, is dat er nu relaties . zijn tussen de tafels .

In een databasemodel worden relaties weergegeven door lijnen die twee entiteiten verbinden. De kenmerken van deze relaties worden weergegeven door verschillende connectoren:

  • Als er een enkele verticale lijn is, heeft de entiteit die zich het dichtst bij die connector bevindt, slechts één rij die door de relatie wordt beïnvloed. Het is de 'één' in één-op-veel.
  • Als er een connector met meerdere lijnen is die eruitziet als een kraaienpoot, heeft de entiteit die het dichtst bij die connector ligt meerdere rijen die door de relatie worden beïnvloed; het is het 'vele'.

Als we naar de afbeelding kijken en de notatie kennen, is het eenvoudig te begrijpen dat het diagram definieert dat elke Order kan veel Order Details . hebben en dat elke Order Detail behoort tot een enkele Order .

Een één-op-veel-relatie tussen tabellen implementeren

Om een ​​een-op-veel-relatie tussen twee tabellen te definiëren, moet de onderliggende tabel verwijzen naar een rij in de bovenliggende tabel. De stappen die nodig zijn om het te definiëren zijn:

  1. Voeg een kolom toe aan de onderliggende tabel waarin de waarde van de primaire identifier wordt opgeslagen. (In feite staan ​​de meeste database-engines toe dat het elke unieke sleutel uit de bovenliggende tabel is, niet alleen de primaire sleutel.) De kolom kan als verplicht worden gedefinieerd, afhankelijk van uw zakelijke behoeften; toch worden er meestal kolommen met vreemde sleutels gemaakt

Opmerking: Het is een goede gewoonte om de naam van de verwijzende kolommen hetzelfde te houden als in de (bovenliggende) tabel waarnaar wordt verwezen. Dit maakt het nog eenvoudiger om de relatie te begrijpen.

  1. Voeg een buitenlandse sleutel toe beperking op de kindertafel. Dit geeft aan dat elke waarde die in deze nieuwe kolom is opgeslagen, verwijst naar een rij in de bovenliggende tabel.

Foreign key-beperkingen zijn een functie die beschikbaar is in de relationele database en die het volgende afdwingt:

  1. Als u een rij toevoegt aan de onderliggende tabel, moet de waarde van de verwijzende kolom overeenkomen met één (en slechts één) waarde in de bovenliggende tabel. (Daarom moet worden verwezen naar een kolom of reeks kolommen die een primaire sleutel of unieke sleutel vormen).
  2. Als iemand probeert een rij uit de bovenliggende tabel te verwijderen of de waarden probeert te wijzigen van de unieke/primaire sleutel die als referentie wordt gebruikt en er een onderliggende tabel is die naar die rij verwijst, zal de bewerking mislukken.

Deze twee eigenschappen zorgen ervoor dat de database zijn integriteit behoudt. Er is geen kans om bestellingen te maken die verwijzen naar een niet-bestaande klant, noch om een ​​klant te verwijderen die al bestellingen heeft.

Een externe sleutel maken

Syntaxis van vreemde sleutels hangt meestal af van de doeldatabase-engine. Nadat u uw logisch model hebt gedefinieerd, kunt u de functie "Fysiek model genereren ..." op Vertabelo logische diagrammen gebruiken om uw (database-agnostische) model om te zetten in een fysiek model dat overeenkomt met uw databaseprovider. Vertabelo genereert ook het vereiste SQL-script waarmee u de tabellen en relaties in uw doeldatabase kunt maken.

Enkele praktische voorbeelden van 1:N-relaties

Laten we nu enkele voorbeelden bekijken van een-op-veel-relaties uit de echte wereld.

Een-op-veel-relatie met primaire sleutels

Dit is waarschijnlijk het meest voorkomende scenario bij het definiëren van een een-op-veel-relatie. De onderliggende tabel gebruikt de primaire sleutelwaarde van de bovenliggende tabel om de relatie tot stand te brengen.

Dit voorbeeld beschrijft een eenvoudige online streamingdienst. Laten we eens kijken wat er in elk van de tabellen is opgeslagen en hoe ze zich verhouden tot de andere tabellen in ons model:

  1. Elk ServiceType bepaalt hoe een account zich 'draagt' (bijv. hoeveel gebruikers tegelijkertijd verbinding kunnen maken met het systeem, of het account Full HD heeft ingeschakeld, enz.). Het heeft één relatie met andere entiteiten:
    • Een een-op-veel-relatie met Account , wat betekent dat elk servicetype veel accounts van dat type kan hebben.
  2. Elke Account slaat informatie over één klant op. Het heeft twee directe relaties met andere entiteiten:
    • Elk account behoort tot één ServiceType , zoals hierboven uitgelegd.
    • Deze tabel heeft een één-op-veel-relatie met het Profile tabel, wat betekent dat meer dan één gebruiker met hetzelfde account verbinding kan maken met ons systeem.
  3. Elk Profile vertegenwoordigt een gebruiker in ons systeem. Het heeft twee relaties met andere entiteiten:
    • Elk profiel hoort bij één Account . Hierdoor kunnen alle gezinsleden (of misschien een groep vrienden) hetzelfde account delen, terwijl ze allemaal hun eigen persoonlijke kenmerken hebben (bijvoorbeeld een profielnaam).
    • Elk profiel heeft een unieke Avatar .
  4. Elke Avatar is een afbeelding waarmee we elke accountgebruiker snel kunnen identificeren. Het heeft één relatie met een andere entiteit:
    • Een een-op-veel-relatie met Profile , wat betekent dat een enkele avatar kan worden toegewezen aan profielen op verschillende accounts.

Een-op-veel-relaties met natuurlijke of surrogaat-unieke sleutels

Het gebruik van surrogaat primaire sleutels is een algemeen aanvaarde manier om tabellen te modelleren. (Primaire surrogaatsleutels worden gegenereerd door de database en hebben geen werkelijke bedrijfswaarde.) Deze methode produceert sleutels die eenvoudiger te gebruiken zijn en enige flexibiliteit toevoegen voor wanneer wijzigingen nodig zijn.

Er zijn echter situaties – b.v. wanneer we moeten communiceren met externe systemen - waarbij het gebruik van een sleutel die in onze database is gegenereerd een slechte benadering is. Voor die scenario's is het meestal beter om natuurlijke sleutels te gebruiken. Dit zijn unieke waarden die deel uitmaken van de entiteit die wordt opgeslagen en die niet automatisch worden gegenereerd door onze database.

Het volgende voorbeeld vertegenwoordigt een basisgegevensmodel van een organisatie die voertuigen bijhoudt (d.w.z. het merk, het model, de kleur en het jaar van de auto), hun eigenaren en alle bijbehorende verkeersovertredingen. Toen we het definieerden, gebruikten we vervangende primaire sleutels om de relaties tussen de voertuigen en merken, modellen en eigenaren vast te stellen, aangezien al deze informatie intern door ons systeem wordt verwerkt.

Hoe kan een politieagent in een andere stad in dit systeem een ​​illegaal geparkeerde auto melden met onze primaire autosleutel (VehicleID )? Dergelijke informatie is natuurlijk niet beschikbaar op het geparkeerde voertuig, maar het kenteken is er wel. Dat betekent dat de eenvoudigste manier om informatie van een externe bron (in dit voorbeeld elke politieafdeling in het land) te ontvangen en te koppelen, is door een natuurlijke unieke sleutel te gebruiken in plaats van een vervangende primaire sleutel.

De fysieke implementatie van dit logische diagram voor SQL Server is hier beschikbaar:

Een-op-veel-relaties aan dezelfde tafel

De vorige voorbeelden waren gericht op relaties tussen twee of meer tabellen, maar er zijn ook scenario's waarin de relatie optreedt tussen rijen van dezelfde tabel. Dit soort een-op-veel-relatie wordt ook wel een hiërarchische relatie genoemd; het wordt in veel systemen gebruikt om boomachtige structuren weer te geven, d.w.z. een organigram, een grootboekrekening of een product en zijn samenstellende delen.

De eerste keer dat u dit soort structuur moet maken, zult u in de verleiding komen om een ​​tabel te definiëren voor elk van de niveaus in uw hiërarchie, zoals weergegeven in het volgende diagram:

Er zijn veel problemen met deze aanpak:

  • Alle tabellen zijn bijna identiek en bevatten identieke informatie.
  • Als uw organisatie een nieuw niveau toevoegt, moet u het gegevensmodel wijzigen en een nieuwe tabel, nieuwe externe sleutels, enz. toevoegen.
  • Als een werknemer een promotie ontvangt, moet u deze van de ene tafel verwijderen en in een andere invoegen.

Daarom is de beste manier om dit soort structuur te modelleren het gebruik van een enkele tabel die naar zichzelf verwijst, zoals weergegeven in dit diagram:

Hier zien we een enkele Employee tabel en een kolom met de naam EmployeeID_Manager . Die kolom verwijst naar een andere werknemer in dezelfde organisatie die de supervisor/manager is van de huidige werknemer.

Ik heb de _Manager . toegevoegd achtervoegsel om onderscheid te maken tussen de ID van de huidige rij en de ID van de manager. (We kunnen ManagerID gebruiken in plaats daarvan, maar ik geef er de voorkeur aan de originele naam van de kolom waarnaar wordt verwezen te behouden en, in die gevallen waarin beide in dezelfde tabel staan, voeg ik een achtervoegsel toe dat de rol die het daadwerkelijk heeft, verklaart).

Het begrijpen van hiërarchische relaties is complexer dan andere een-op-veel-relaties. Maar als je de tabel vergeet waarin alle informatie is opgeslagen en je voorstelt dat er eigenlijk verschillende tabellen zijn, die elk een niveau in de hiërarchie vertegenwoordigen, is het een beetje makkelijker om te visualiseren. Stel je voor dat je de relatie tussen twee entiteiten maakt en ze vervolgens combineert tot één entiteit.

Wat nu?

De gegeven voorbeelden helpen u bij het identificeren van verschillende scenario's die een een-op-veel-relatie vereisen. U kunt beginnen met het ontwerpen van uw eigen databasestructuur met behulp van de Vertabelo Database Modeler, een webgebaseerde tool waarmee u niet alleen een logisch model kunt genereren, maar ook een fysieke versie ervan kunt maken voor de databaseprovider die u nodig heeft.

Nu is het jouw beurt - gebruik het opmerkingengedeelte om ons je mening over dit artikel te vertellen, eventuele aanvullende vragen te stellen of je ervaringen met databasemodellering te delen.


  1. STRING_SPLIT() in SQL Server 2016:vervolg #2

  2. Oracle - Welk TNS Names-bestand gebruik ik?

  3. Hoe de serverstatus in MySQL Workbench te controleren met behulp van de GUI

  4. Verschillende CURRENT_TIMESTAMP en SYSDATE in orakel