sql >> Database >  >> RDS >> Sqlserver

Een samengestelde externe sleutel maken in SQL Server (T-SQL-voorbeeld)

Een samengestelde externe sleutel is een externe sleutel die uit meerdere kolommen bestaat.

Dit artikel bevat een voorbeeld van het maken van een samengestelde externe sleutel met Transact-SQL in SQL Server.

U kunt een samengestelde externe sleutel maken, net zoals u een enkele externe sleutel zou maken, behalve dat u in plaats van slechts één kolom op te geven, de naam van twee of meer kolommen opgeeft, gescheiden door een komma.

Zoals dit:

CONSTRAINT FK_FKName FOREIGN KEY
 (FKColumn1, FKColumn2)
REFERENCES PrimaryKeyTable (PKColumn1, PKColumn2)

Voorbeeld 1 – Maak een samengestelde externe sleutel

Hier is een voorbeeld van een database die een samengestelde externe sleutel (en een samengestelde primaire sleutel) gebruikt.

Voor dit voorbeeld zal ik een database maken met de naam BandTest :

CREATE DATABASE BandTest;

Nu de database is gemaakt, gaan we verder met het maken van de tabellen.

USE BandTest;

CREATE TABLE Musician (
MusicianId int NOT NULL,
FirstName varchar(60),
LastName varchar(60),
CONSTRAINT PK_Musician PRIMARY KEY (MusicianID)
);

CREATE TABLE Band (
BandId int NOT NULL,
BandName varchar(255),
CONSTRAINT PK_Band PRIMARY KEY (BandId)
);

CREATE TABLE BandMember (
MusicianId int NOT NULL,
BandId int NOT NULL,
CONSTRAINT PK_BandMember PRIMARY KEY (MusicianID, BandId),
CONSTRAINT FK_BandMember_Band FOREIGN KEY (BandId) REFERENCES Band(BandId),
CONSTRAINT FK_BandMember_Musician FOREIGN KEY (MusicianId) REFERENCES Musician(MusicianId)
);

CREATE TABLE MembershipPeriod (
MembershipPeriodId int NOT NULL,
MusicianId int NOT NULL,
BandId int NOT NULL,
StartDate date NOT NULL,
EndDate date NULL,
CONSTRAINT PK_MembershipPeriod PRIMARY KEY (MembershipPeriodID),
CONSTRAINT FK_MembershipPeriod_BandMember FOREIGN KEY (MusicianID, BandId) REFERENCES BandMember(MusicianID, BandId)
);

In dit voorbeeld is de BandMember tabel heeft een primaire sleutel met meerdere kolommen. De MembershipPeriod tabel heeft een externe sleutel die verwijst naar die primaire sleutel met meerdere kolommen. Daarom bevatten zowel de primaire als de refererende sleuteldefinities de kolommen gescheiden door een komma.

De redenering achter het bovenstaande databaseontwerp is dat een muzikant mogelijk lid kan zijn van veel bands. Elke band kan ook veel muzikanten hebben. We hebben dus een veel-op-veel relatie. Dit is de reden waarom het BandMember tabel wordt gemaakt – deze wordt gebruikt als een kruisverwijzingstabel tussen de Musician tabel en de Band tafel. In dit geval heb ik ervoor gekozen om een ​​samengestelde primaire sleutel te gebruiken.

Maar een muzikant kan ook meer dan eens lid zijn van een band (een muzikant kan bijvoorbeeld een band verlaten om later terug te keren). Daarom is de MembershipPeriod tabel kan worden gebruikt om alle periodes vast te leggen waarin elke muzikant lid is geweest van elke band. Dit moet verwijzen naar de samengestelde primaire sleutel op het BandMember tabel, en dus moet ik een externe sleutel met meerdere kolommen maken.

Voorbeeld 2 – Gegevens invoegen

Nadat ik zojuist de bovenstaande code heb uitgevoerd, kan ik nu de database met gegevens laden:

INSERT INTO Musician
VALUES 
( 1, 'Ian', 'Paice' ),
( 2, 'Roger', 'Glover' ),
( 3, 'Richie', 'Blackmore' ),
( 4, 'Rod', 'Evans' ),
( 5, 'Ozzy', 'Osbourne' );

INSERT INTO Band
VALUES 
( 1, 'Deep Purple' ),
( 2, 'Rainbow' ),
( 3, 'Whitesnake' ),
( 4, 'Iron Maiden' );

INSERT INTO BandMember
VALUES 
( 1, 1 ),
( 1, 3 ),
( 2, 1 ),
( 2, 2 ),
( 3, 1 ),
( 3, 2 ),
( 4, 1 );

INSERT INTO MembershipPeriod
VALUES 
( 1, 1, 1, '1968-03-01', '1976-03-15' ),
( 2, 1, 1, '1984-04-01', NULL ),
( 3, 1, 3, '1979-08-01', '1982-01-01' ),
( 4, 2, 1, '1969-01-01', '1973-06-29' ),
( 5, 2, 1, '1984-04-01', NULL ),
( 6, 2, 2, '1979-01-01', '1984-01-01' ),
( 7, 3, 1, '1968-03-01', '1975-06-21' ),
( 8, 3, 1, '1984-04-01', '1993-11-17' ),
( 9, 3, 2, '1975-02-01', '1984-04-01' ),
( 10, 3, 2, '1993-11-17', '1997-05-31' ),
( 11, 3, 2, '2015-01-01', NULL ),
( 12, 4, 1, '1968-03-01', '1969-12-01' );

Voorbeeld 3 – Basisquery

Hier is een voorbeeld van een query die op de database kan worden uitgevoerd:

SELECT 
  CONCAT(m.FirstName, ' ', m.LastName) AS 'Musician',
  b.BandName AS 'Band',
  mp.StartDate AS 'Start',
  mp.EndDate AS 'End'
FROM Musician m
JOIN BandMember bm
  ON m.MusicianId = bm.MusicianId
JOIN Band b 
  ON b.BandId = bm.BandId AND m.MusicianId = bm.MusicianId
JOIN MembershipPeriod mp
ON mp.BandId = b.BandId AND mp.MusicianId = m.MusicianId;

Resultaat:

+------------------+-------------+------------+------------+
| Musician         | Band        | Start      | End        |
|------------------+-------------+------------+------------|
| Ian Paice        | Deep Purple | 1968-03-01 | 1976-03-15 |
| Ian Paice        | Deep Purple | 1984-04-01 | NULL       |
| Ian Paice        | Whitesnake  | 1979-08-01 | 1982-01-01 |
| Roger Glover     | Deep Purple | 1969-01-01 | 1973-06-29 |
| Roger Glover     | Deep Purple | 1984-04-01 | NULL       |
| Roger Glover     | Rainbow     | 1979-01-01 | 1984-01-01 |
| Richie Blackmore | Deep Purple | 1968-03-01 | 1975-06-21 |
| Richie Blackmore | Deep Purple | 1984-04-01 | 1993-11-17 |
| Richie Blackmore | Rainbow     | 1975-02-01 | 1984-04-01 |
| Richie Blackmore | Rainbow     | 1993-11-17 | 1997-05-31 |
| Richie Blackmore | Rainbow     | 2015-01-01 | NULL       |
| Rod Evans        | Deep Purple | 1968-03-01 | 1969-12-01 |
+------------------+-------------+------------+------------+

We kunnen nu dus zien op welke datums elke muzikant lid was van elke band, zelfs als ze meerdere keren lid waren.

Voorbeeld 4 – Iets gewijzigde zoekopdracht

We zouden de bovenstaande zoekopdracht kunnen wijzigen om de resultaten in een iets beter leesbaar formaat te leveren:

SELECT 
  CONCAT(m.FirstName, ' ', m.LastName) AS 'Musician',
  b.BandName AS 'Band',
  STRING_AGG(
    CONCAT(FORMAT(mp.StartDate, 'yyyy'), '-', ISNULL(FORMAT(mp.EndDate, 'yyyy'), 'present')), ', ') AS 'Time with the band'
FROM Musician m
JOIN BandMember bm
  ON m.MusicianId = bm.MusicianId
JOIN Band b 
  ON b.BandId = bm.BandId AND m.MusicianId = bm.MusicianId
JOIN MembershipPeriod mp
ON mp.BandId = b.BandId AND mp.MusicianId = m.MusicianId
GROUP BY m.FirstName, m.LastName, b.BandName;

Resultaat:

+------------------+-------------+------------------------------------+
| Musician         | Band        | Time with the band                 |
|------------------+-------------+------------------------------------|
| Ian Paice        | Deep Purple | 1968-1976, 1984-present            |
| Ian Paice        | Whitesnake  | 1979-1982                          |
| Richie Blackmore | Deep Purple | 1968-1975, 1984-1993               |
| Richie Blackmore | Rainbow     | 1975-1984, 1993-1997, 2015-present |
| Rod Evans        | Deep Purple | 1968-1969                          |
| Roger Glover     | Deep Purple | 1969-1973, 1984-present            |
| Roger Glover     | Rainbow     | 1979-1984                          |
+------------------+-------------+------------------------------------+

Dit voorbeeld maakt gebruik van de STRING_AGG() functie om de verschillende tijdsperioden voor elke muzikant samen te voegen. Dit vermindert uiteindelijk het aantal vereiste rijen en stelt ons in staat om de tijdsperioden samen in hetzelfde veld te groeperen.

Ik maak ook gebruik van de ISNULL() functie, waarmee ik alle NULL-waarden in iets zinvoller kan veranderen.

Merk op dat ISNULL() vereist dat het tweede argument van een type is dat impliciet kan worden geconverteerd naar het type van het eerste argument. In dit geval was het eerste argument oorspronkelijk een datum type, wat betekent dat ik geen string zou kunnen gebruiken. In dit geval heb ik echter besloten om de FORMAT() . te gebruiken functie om de datum op te maken waarde. Deze functie converteert impliciet de datum waarde toe aan een string, en daarom kon ik een string gebruiken voor het tweede argument.


  1. Opgeslagen Oracle-procedure aanroepen vanuit C#?

  2. Postgres SSL SYSCALL-fout:EOF gedetecteerd met python en psycopg

  3. Hoe te groeperen op jaar in SQL

  4. Verbinding maken met een externe PostgreSQL-database via SSL met Python