sql >> Database >  >> RDS >> Database

SQL FOREIGN KEY CONSTRAINT:de ultieme, gemakkelijke gids voor beginners

Nieuweling? Dan is een externe SQL-sleutel misschien vreemd voor u.

Je hebt misschien verschillende meningen gehoord over externe SQL-sleutels. Als je dat nog niet hebt gedaan, zul je dat binnenkort doen. Of uw ervaring zal uw uitzicht beïnvloeden. Het belangrijkste om te weten is dat externe sleutels een must zijn in relationele databases.

Toch kunnen sommige ontwikkelaars externe sleutels verwijderen of negeren wanneer ze met enkele complicaties worden geconfronteerd. Dus wat te doen? Wel of niet de externe sleutel gebruiken? Zullen er momenten zijn waarop u ze niet hoeft te gebruiken?

Deze gids is voor u om te zien hoe belangrijk dit ding is. Je zult ook enkele valkuilen in code kennen en leren hoe je ze kunt oplossen. Daarnaast gebruiken we natuurlijk praktijkvoorbeelden. Er is niets dat je niet aankunt.

Wat is een externe SQL-sleutel?

Eerste dingen eerst. Wat is een externe sleutel in SQL? In een paar woorden, het is een sleutel die 2 tabellen met elkaar verbindt. Stel dat u een bovenliggende tabel en een onderliggende tabel heeft. Er is enige overeenkomst waardoor ze een ouder en een kind zijn - de sleutel die deze 2 tabellen met elkaar verbindt.

In SQL-databases heeft een externe sleutel echter niet alleen betrekking op tabellen. Het versterkt de relatie. Daarom wordt het een externe sleutelbeperking genoemd.

Er treedt een fout op als u een onderliggend record probeert toe te voegen met een refererende-sleutelwaarde die niet bestaat in de primaire sleutels van de bovenliggende tabel. Later zullen we codevoorbeelden zien die dit illustreren.

Welke tabellen moeten beperkingen hebben voor externe SQL-sleutels?

Onderliggende tabellen kunnen externe sleutels hebben. Een externe sleutel kan verwijzen naar een andere tabel. Er kunnen ook verschillende externe sleutels in een "kind" -tabel zijn. In SQL Server kan een externe sleutel verwijzen naar een primaire sleutel of een unieke sleutel in een andere tabel.

Hoe zit het met zelfreferentie?

Dit gaat buiten de algemene definitie van een externe sleutel. Een zelfreferentie betekent dat u een externe sleutel kunt toewijzen die verwijst een andere kolom in dezelfde tabel . SQL Server, MySQL en Oracle ondersteunen dit.

Zelfreferentie is van toepassing wanneer u hiërarchieën wilt creëren, zoals de manager-stafrelatie. Het is toegestaan, maar de meeste implementaties van buitenlandse sleutels bevinden zich tussen 2 tabellen.

Later zullen we voorbeelden hebben.

4 Voordelen van het gebruik van externe SQL-sleutels

Laten we de primaire sleutel en externe sleutel in SQL in detail onderzoeken. Wat maakt externe sleutels een must-have voor een SQL-database? Laten we 4 punten onderzoeken (hier doet de syntaxis van de beperking er niet toe).

1. Vermijd "ontbrekende" gegevens

"Ontbrekende" gegevens zijn externe sleutelwaarden uit onderliggende tabellen zonder bijbehorende primaire sleutelwaarden uit de bovenliggende tabel. Ze worden ook wel weesrijen genoemd. Als het gebeurt, kunnen we zeggen dat de database weinig of geen referentiële integriteit heeft.

Met buitenlandse sleutelbeperkingen afgedwongen, zullen "ontbrekende" gegevens helemaal niet voorkomen. De database-engine staat het verwijderen van een primaire sleutelwaarde waarnaar wordt verwezen door een andere tabel niet toe. Evenzo zal het invoegen van een externe sleutel in de onderliggende tabel die niet bestaat in de primaire sleutels van de bovenliggende tabel, een fout veroorzaken.

Wat is het ergste dat kan gebeuren als u de externe sleutelbeperkingen niet gebruikt? Hier zijn er een paar:

  • Klanten ontvangen geen producten waarvoor ze hebben betaald.
  • Behandeling wordt niet toegediend aan patiënten.
  • Ontbrekende checklists slaan veiligheidsmaatregelen over.

Je kunt dit soort dingen buiten de database afhandelen, maar je moet het wel coderen. Meer hierover volgt.

Stel dat een ontwikkelaar in uw organisatie met dezelfde beperking omging buiten de database om. Zal hij verantwoordelijk zijn en het probleem in productie oplossen als de code faalt? Ik denk het niet. En wat als u de databasebeheerder bent? Dan moet je hun rotzooi opruimen. Niet zo bemoedigend als je het mij vraagt.

2. Vermijd inconsistente rapporten

Het heeft betrekking op het eerste punt. Als er gegevens 'ontbreken', verschijnen er inconsistente totalen in verschillende rapporten. Details komen niet overeen met de samenvattingen. Verweesde rijen tellen op tot de totalen van de samenvattingen. Ondertussen legde het gedetailleerde rapport geen zwevende rijen vast vanwege een inner join naar de bovenliggende tabellen.

Als het jouw taak is om je database in goede staat te houden, ruim je deze rotzooi ook op.

3. Geen code nodig om verweesde rijen te vermijden

Foreign key-beperkingen werken als zelfreinigende middelen. In plaats van dat u de rommel opruimt, doet de database dit door verweesde rijen niet toe te staan. Foreign key-beperkingen fungeren ook als politie. Ze arresteren de gebrekkige logica die verweesde rijen veroorzaakt en behandelen het als een misdaad die buiten de database om wordt gepleegd.

Wilt u een glanzende database zonder verweesde rijen? Natuurlijk doe je dat. Als je de gegevens ooit wilt analyseren, zou je blij zijn dat je buitenlandse sleutels had gebruikt. Deze database is een goede bron voor het kopiëren van de benodigde gegevens naar uw verzamelgebied.

4. Snel tabelrelaties in een diagram begrijpen

SQL Server Management Studio heeft een ingebouwde diagramtool voor uw database. Primaire en externe sleutels maken het databasediagram in één oogopslag informatief. Het hangt echter af van hoeveel tabellen met relaties u in het diagram hebt opgenomen.

Diagrammen helpen nieuwe teamleden de gegevensstructuur te begrijpen. Voor senior teamgenoten kan het ook handig zijn als documentatie.

Wanneer SQL Foreign Key een "probleem" kan zijn (plus de oplossing)

Om oude gegevens naar een nieuwe database te migreren, voegt u records in bulk in. Als de brondatabase een lage referentiële integriteit heeft, zal het lastig zijn om records uit de bron in te voegen. De reden is dat hier en daar fouten met vreemde sleutels verschijnen.

Is er een oplossing? Je hebt 2 opties.

  1. Zorg ervoor dat u eerst de referentietabellen of de bovenliggende tabellen vult. Vul daarna de onderliggende tabellen in. Een complicatie is erg traag. In andere gevallen treden meer beperkingen met externe sleutels op. Als het laatste geval zich voordoet, moet u de volgorde van invoegingen opnieuw evalueren en ervoor zorgen dat eerst de primaire sleutels worden ingevoegd. Als er een "langzaam" probleem is, overweeg dan de volgende optie.
  2. Schakel de externe sleutels tijdelijk uit en schakel ze in nadat de migratie is voltooid (en opgeschoond). U kunt dit doen in SQL Server Management Studio of T-SQL ALTER TABLE gebruiken. Het is echter gemakkelijker gezegd dan gedaan. Op dit punt heb je naast je verstand en wilskracht meer geduld nodig. Later zullen we de syntaxis vinden voor het in- en uitschakelen van externe sleutels.

Een ander ding om te overwegen is het gebruik van een database als verzamelgebied voor OLAP of gegevensanalyse. Stel dat de transactiebrondatabase vrij is van zwevende rijen. Of u kunt deze rijen via code vermijden. Dan kunt u ervoor kiezen om geen externe sleutels te gebruiken. Buitenlandse sleutels vertragen bulkinvoegingen en updates, vooral bij gigantische datasets.

3 eenvoudige manieren om SQL Foreign Key-beperkingen toe te voegen, te bewerken en te verwijderen

Wat is er nodig om externe sleutels toe te voegen, te bewerken of te verwijderen? Het is gemakkelijk met deze 3 tips.

De eerste twee stappen gebruiken een grafische gebruikersinterface. Tools zoals SQL Server Management Studio of dbForge Studio voor SQL Server zijn zeer goede kandidaten. De derde gebruikt T-SQL-code. De keuze voor een GUI of T-SQL-code is afhankelijk van de situatie.

1. Table Designer gebruiken om SQL Foreign Key-beperking toe te voegen, te bewerken en te verwijderen

Het is in SQL mogelijk om externe sleutelbeperkingen toe te voegen bij het maken of wijzigen van een tabelstructuur met behulp van Table Designer in SSMS. Afbeelding 1 hieronder laat zien hoe u toegang krijgt vanuit het hoofdmenu wanneer de tabelstructuur open is.

Een andere optie is om ergens in de tabelontwerper met de rechtermuisknop te klikken en Relaties te selecteren vanuit het contextmenu:

Nadat u Relaties heeft geselecteerd , de Buitenlandse sleutelrelaties venster verschijnt:

In de Buitenlandse sleutelrelaties venster, kunt u ervoor kiezen om een ​​nieuwe externe sleutel toe te voegen of een bestaande te bewerken/verwijderen.

Als u ervoor kiest om toe te voegen of te bewerken, klikt u om de Tabellen en kolommen . uit te vouwen Specificaties. Klik vervolgens op de ellips knop om de primaire en externe sleuteltabellen te definiëren of te bewerken.

Van daaruit kunt u de kolommen met primaire en externe sleutels aangeven.

Nadat u de primaire en externe sleutels hebt gedefinieerd, klikt u op OK . Navigeer vervolgens terug naar de tabelontwerper en sla de wijzigingen op.

2. Databasediagram gebruiken om SQL Foreign Key-beperking toe te voegen, te bewerken en te verwijderen

U kunt het databasediagram gebruiken om beperkingen voor externe SQL-sleutels te maken. Afbeelding 5 laat zien hoe u een relatie tussen twee tabellen kunt maken door op de refererende-sleuteltabel te klikken en deze naar de primaire-sleuteltabel te slepen.

Wanneer u de muis loslaat, worden de Tabellen en kolommen venster verschijnt zoals in figuur 4. Vervolgens kunt u de kolommen met primaire en externe sleutels aangeven. Klik vervolgens op OK.

Als u een bestaande relatie wilt bewerken, klikt u met de rechtermuisknop op een relatie in het diagram. Selecteer vervolgens Eigenschappen :

Dan, in de Eigenschappen venster, vouw Tabellen en kolommen . uit en klik op het ellips knop:

Na het klikken op de ellips knop, de Tabellen en kolommen venster zal verschijnen. U kunt de kolommen met primaire en externe sleutels wijzigen (zie nogmaals Afbeelding 4 hierboven).

Ondertussen een relatie verwijderen vereist rechtsklikken op een bestaande relatie. Selecteer Verwijder relaties uit database en klik op Ja wanneer daarom wordt gevraagd.

3. T-SQL gebruiken om SQL Foreign Key-beperking toe te voegen, te bewerken en te verwijderen

De derde manier om een ​​externe sleutel toe te voegen is via de T-SQL-code. U kunt SQL CREATE TABLE gebruiken en de externe-sleutelbeperking toevoegen. Of je kunt ALTER TABLE ook gebruiken om deze beperking toe te voegen nadat je de tabel hebt gemaakt.

Hier is de syntaxis voor het gebruik van CREATE TABLE:

-- Single-column foreign key
CREATE TABLE Table2
(ID INT IDENTITY(1,1) NOT NULL PRIMARY KEY CLUSTERED,
 col1 INT NULL REFERENCES Table1(col1)
)
GO

Nadat u de kolomnaam en het type hebt gedefinieerd, kunt u REFERENCES toevoegen aan een tabel en kolom. De bovenstaande syntaxis toont de Tabel1 tafel op de col1 kolom. Merk op dat kolomnamen in beide tabellen hetzelfde moeten zijn om geldig te zijn voor buitenlandse sleutels.

De bovenstaande syntaxis is voor externe sleutels met één kolom. Als u meerdere kolommen als externe sleutels nodig heeft, gebruikt u de FOREIGN KEY-clausule zoals hieronder:

-- Multiple-column foreign key
CREATE TABLE Table2
(ID INT IDENTITY(1,1) NOT NULL PRIMARY KEY CLUSTERED,
 col1 INT NOT NULL,
 col2 INT NOT NULL,
 col3 VARCHAR(10) NULL
 CONSTRAINT FK_Table1_Table2 FOREIGN KEY(col1, col2)
	REFERENCES Table1(col1,col2)
)
GO

Nadat u de tabel hebt gemaakt, kunt u externe sleutels toevoegen met ALTER TABLE. Dit is de syntaxis:

ALTER TABLE Table2 WITH CHECK ADD CONSTRAINT FK_Table1_Table2_2 FOREIGN KEY(col3)
	REFERENCES Table3(col1)
GO

Om een ​​externe sleutelbeperking te verwijderen, kunt u ALTER TABLE gebruiken met DROP CONSTRAINT:

ALTER TABLE Table2 
DROP CONSTRAINT FK_Table1_Table2_2
GO

Nu kunnen we 3 manieren samenvatten om externe sleutels toe te voegen, te bewerken en te verwijderen:

SQL (MySQL) Foreign Key Constraint-voorbeelden

Kindertabel met 1 verwijzing naar een bovenliggende tabel

-- Single Reference
CREATE TABLE [dbo].[Countries](
	[CountryID] [int] IDENTITY(1,1) NOT NULL,
	[Country] [nvarchar](50) NOT NULL,
	[ContinentID] [int] NULL,
	[Modified] [datetime] NOT NULL,
 CONSTRAINT [PK_Country] PRIMARY KEY CLUSTERED 
(
	[CountryID] ASC
))
GO

ALTER TABLE [dbo].[Countries]  WITH CHECK ADD CONSTRAINT [FK_Countries_Continent] FOREIGN KEY([ContinentID])
REFERENCES [dbo].[Continent] ([ContinentID])

GO

ALTER TABLE [dbo].[Countries] CHECK CONSTRAINT [FK_Countries_Continent]
GO

Bekijk figuur 9 hieronder om deze relatie te visualiseren:

De ContinentID is de sleutel die de twee tabellen met elkaar verbindt.

Kindertabel met meerdere referenties

De Sportwagen tabel heeft meerdere verwijzingen naar drie verschillende tabellen:

-- Multiple References
CREATE TABLE [dbo].[SportsCars](
	[SportsCarID] [int] IDENTITY(1,1) NOT NULL,
	[ManufacturerID] [int] NULL,
	[StyleID] [int] NULL,
	[CountryID] [int] NULL,
	[Model] [nvarchar](50) NOT NULL,
	[Years] [varchar](50) NOT NULL,
	[Notes] [varchar](255) NOT NULL,
	[Modified] [datetime] NOT NULL,
 CONSTRAINT [PK_SportsCars] PRIMARY KEY CLUSTERED 
(
	[SportsCarID] ASC
))
GO

ALTER TABLE [dbo].[SportsCars] WITH CHECK ADD CONSTRAINT [FK_SportsCars_Country] FOREIGN KEY([CountryID])
REFERENCES [dbo].[Countries] ([CountryID])
GO

ALTER TABLE [dbo].[SportsCars] CHECK CONSTRAINT [FK_SportsCars_Country]
GO

ALTER TABLE [dbo].[SportsCars] WITH CHECK ADD CONSTRAINT [FK_SportsCars_Manufacturer] FOREIGN KEY([ManufacturerID])
REFERENCES [dbo].[Manufacturers] ([ManufacturerID])
GO

ALTER TABLE [dbo].[SportsCars] CHECK CONSTRAINT [FK_SportsCars_Manufacturer]
GO

ALTER TABLE [dbo].[SportsCars] WITH CHECK ADD CONSTRAINT [FK_SportsCars_Styles] FOREIGN KEY([StyleID])
REFERENCES [dbo].[Styles] ([StyleID])
GO

ALTER TABLE [dbo].[SportsCars] CHECK CONSTRAINT [FK_SportsCars_Styles]
GO

Zo ziet het eruit in een databasediagram:

Zelfreferentie

Positiehiërarchieën tonen zelfreferentie in de volgende tabel:

CREATE TABLE [dbo].[Ranks](
	[RankId] [int] IDENTITY(1,1) NOT NULL,
	[Rank] [varchar](50) NOT NULL,
	[RankLevel] [smallint] NOT NULL,
	[RankParentId] [int] NULL,
 CONSTRAINT [PK_Ranks] PRIMARY KEY CLUSTERED 
(
	[RankId] ASC
)) ON [PRIMARY]
GO

ALTER TABLE [dbo].[Ranks] WITH CHECK ADD CONSTRAINT [FK_Ranks_Ranks] FOREIGN KEY([RankParentId])
REFERENCES [dbo].[Ranks] ([RankId])
GO

ALTER TABLE [dbo].[Ranks] CHECK CONSTRAINT [FK_Ranks_Ranks]
GO

Het diagram van deze zelfverwijzing is eenvoudig. De lijn wijst naar dezelfde tabel in zelfreferentie.

Met ON UPDATE en ON DELETE

Met ON UPDATE CASCADE zal het updaten van een primaire sleutelkolomwaarde ook de refererende sleutelwaarden in gerelateerde tabellen bijwerken. Ondertussen, wanneer u ON DELETE CASCADE gebruikt, zal het verwijderen van een primaire sleutel ook externe sleutels verwijderen. De standaard voor ON UPDATE en ON DELETE is GEEN ACTIE.

Hier is een voorbeeld van UPDATE en DELETE CASCADE:

ALTER TABLE [dbo].[Countries] WITH CHECK ADD CONSTRAINT [FK_Countries_Continent] FOREIGN KEY([ContinentID])
REFERENCES [dbo].[Continent] ([ContinentID]) 
ON UPDATE CASCADE 
ON DELETE CASCADE
GO

Een SQL Foreign Key-beperking uitschakelen

Het volgende schakelt een bestaande externe sleutelbeperking uit. Merk op dat de relatie nog steeds bestaat.

ALTER TABLE [dbo].[SportsCars] NOCHECK CONSTRAINT [FK_SportsCars_Country]
GO

Dit is niet de standaardinstelling en wordt niet aanbevolen. Maar om bulkinvoegingen en updates te versnellen, kunt u de externe sleutel tijdelijk uitschakelen, zoals hierboven. Nadat je klaar bent, moet je het terugzetten met CHECK CONSTRAINT.

ALTER TABLE [dbo].[SportsCars] CHECK CONSTRAINT [FK_SportsCars_Country]
GO

Gotcha's en oplossingen

Dit gedeelte laat u zien wat er gebeurt als u records INSERT, BIJWERKT of VERWIJDERT met externe sleutels. Dit veronderstelt ook dat externe sleutels niet zijn uitgeschakeld met NOCHECK-BEPERKING. Dit zal u helpen wanneer u deze veelvoorkomende problemen tegenkomt.

Aan INSERT

-- This will cause an error because countryID = 47 does not exist in the Countries table
INSERT INTO SportsCars 
(ManufacturerID, StyleID, CountryID, Model, Years, Notes) 
VALUES (108, 10, 47, 'F2', '2021', 'Limited Edition')
GO

Hier is de foutmelding:

Msg 547, Level 16, State 0, Line 56
The INSERT statement conflicted with the FOREIGN KEY constraint "FK_SportsCars_Country". The conflict occurred in database "Vehicles", table "dbo.Countries", column 'CountryID'.
The statement has been terminated.

De oplossing :Land-ID toevoegen =47 in de Landen tafel eerst. Voer vervolgens de bovenstaande instructie INSERT opnieuw uit. De reeks begint met het invoegen van records in de bovenliggende tabel en vervolgens in de onderliggende tabel.

Bij UPDATE

-- Update CountryID to 47 will trigger an error.
UPDATE SportsCars
SET CountryID = 47
WHERE ManufacturerID = 108
GO

Dit is de UPDATE-fout:

Msg 547, Level 16, State 0, Line 60
The UPDATE statement conflicted with the FOREIGN KEY constraint "FK_SportsCars_Country". The conflict occurred in database "Vehicles", table "dbo.Countries", column 'CountryID'.
The statement has been terminated.

De oplossing :Land-ID toevoegen =47 in de Landen tafel. Voer vervolgens de UPDATE-instructie opnieuw uit.

Op VERWIJDEREN

-- This will trigger an error because ManufacturerID = 108 is referenced in the SportsCars table
DELETE FROM Manufacturers
WHERE ManufacturerID = 108

Deze code activeert de onderstaande fout:

Msg 547, Level 16, State 0, Line 64
The DELETE statement conflicted with the REFERENCE constraint "FK_SportsCars_Manufacturer". The conflict occurred in database "Vehicles", table "dbo.SportsCars", column 'ManufacturerID'.
The statement has been terminated.

De oplossing :verwijder de bijbehorende records uit de SportsCars tabel met FabrikantID =108. Voer vervolgens de bovenstaande DELETE-instructie opnieuw uit. Een andere manier is om ON DELETE CASCADE in te schakelen, indien van toepassing. De reeks begint met het verwijderen van records uit de onderliggende tabellen en vervolgens - uit de bovenliggende tabel.

Afhaalmaaltijden

Dus, zijn buitenlandse sleutels nog steeds vreemd voor u?

Laten we een samenvatting geven van wat we tot nu toe hebben geleerd.

  • Buitenlandse sleutels koppelen twee tabellen (of één tabel bij gebruik van zelfverwijzing). Je hebt ze nodig om referentiële integriteit te garanderen.
  • U kunt een GUI-tool of T-SQL gebruiken om de beperkingen voor externe sleutels toe te voegen, te bewerken of te verwijderen.
  • Voor GUI-tools kunt u SQL Server Management Studio of dbForge Studio voor SQL Server gebruiken. Beide bieden databasediagrammen en tabelontwerpers om tabellen te maken met primaire en externe sleutels.
  • CREATE TABLE en ALTER TABLE zijn geschikt voor het toevoegen en verwijderen van de externe sleutelbeperkingen.
  • Je kunt externe sleutels tijdelijk uitschakelen met NOCHECK CONSTRAINT in ALTER TABLE. Dit versnelt bulkinvoegingen en updates. Maar zorg ervoor dat je het weer inschakelt met CHECK CONSTRAINT.
  • Om gedoe met externe sleutels te voorkomen, moet u ervoor zorgen dat u de juiste volgorde aanhoudt. Voeg voor INSERT en UPDATE eerst in de bovenliggende tabel in en vervolgens in de onderliggende tabellen. Voor VERWIJDEREN:verwijder eerst de onderliggende records en verwijder vervolgens de bovenliggende records.

Wil je iets toevoegen om nieuwelingen te helpen buitenlandse sleutels onder de knie te krijgen? De Opmerkingen sectie staat open voor uw heldere ideeën. Als je dit bericht leuk vindt, deel het dan op je favoriete sociale mediaplatforms.


  1. Best practices voor back-ups voor MySQL, MariaDB en Galera Cluster

  2. T-SQL datetime afgerond op de dichtstbijzijnde minuut en de dichtstbijzijnde uren met gebruik van functies

  3. Vraag extreem traag in code maar snel in SSMS

  4. Python-module cx_Oracle-module kan niet worden gevonden