sql >> Database teknologi >  >> RDS >> Sqlserver

Sådan opretter du en sammensat fremmednøgle i SQL Server (T-SQL-eksempel)

En sammensat fremmednøgle er en fremmednøgle, der består af flere kolonner.

Denne artikel giver et eksempel på oprettelse af en sammensat fremmednøgle ved hjælp af Transact-SQL i SQL Server.

Du kan oprette en sammensat fremmednøgle, ligesom du ville oprette en enkelt fremmednøgle, bortset fra at du i stedet for kun at angive én kolonne angiver navnet på to eller flere kolonner, adskilt af et komma.

Sådan:

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

Eksempel 1 – Opret en sammensat fremmednøgle

Her er et eksempel på en database, der bruger en sammensat fremmednøgle (og en sammensat primærnøgle).

Til formålet med dette eksempel vil jeg oprette en database kaldet BandTest :

CREATE DATABASE BandTest;

Nu hvor databasen er oprettet, lad os gå videre og oprette tabellerne.

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)
);

I dette eksempel er BandMember tabellen har en primær nøgle med flere kolonner. MembershipPeriod tabellen har en fremmednøgle, der refererer til den primære nøgle med flere kolonner. Derfor inkluderer både primær- og fremmednøgledefinitionerne kolonnerne adskilt af et komma.

Begrundelsen bag ovenstående databasedesign er, at en musiker potentielt kan være medlem af mange bands. Desuden kan hvert band have mange musikere. Så vi har et mange-til-mange forhold. Det er derfor BandMember tabel oprettes – den bruges som en krydsreferencetabel mellem Musician tabellen og Band bord. I dette tilfælde har jeg valgt at bruge en sammensat primærnøgle.

Men en musiker kan også være medlem af et band ved mere end én lejlighed (f.eks. kan en musiker forlade et band for at vende tilbage senere). Derfor er MembershipPeriod tabel kan bruges til at optage alle de perioder, hver musiker har været medlem af hvert band. Dette skal referere til den sammensatte primærnøgle på BandMember tabel, og derfor skal jeg oprette en fremmednøgle med flere kolonner.

Eksempel 2 – Indsæt data

Efter lige at have kørt ovenstående kode, kan jeg nu indlæse databasen med data:

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' );

Eksempel 3 – Grundlæggende forespørgsel

Her er et eksempel på en forespørgsel, der kunne køres mod databasen:

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;

Resultat:

+------------------+-------------+------------+------------+
| 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 |
+------------------+-------------+------------+------------+

Så vi kan nu se, hvilke datoer hver musiker var medlem af hvert band, selvom de var medlem ved flere lejligheder.

Eksempel 4 – Lidt ændret forespørgsel

Vi kunne ændre ovenstående forespørgsel for at give resultaterne i et lidt mere læsbart format:

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;

Resultat:

+------------------+-------------+------------------------------------+
| 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                          |
+------------------+-------------+------------------------------------+

Dette eksempel udnytter STRING_AGG() funktion til at sammenkæde de forskellige tidsperioder for hver musiker. Dette ender med at reducere antallet af krævede rækker og giver os mulighed for at gruppere tidsperioderne i det samme felt.

Jeg udnytter også ISNULL() funktion, som giver mig mulighed for at ændre alle NULL-værdier til noget mere meningsfuldt.

Bemærk at ISNULL() kræver, at det andet argument er af en type, der implicit kan konverteres til typen af ​​det første argument. I dette tilfælde var det første argument oprindeligt en dato type, hvilket betyder, at jeg ikke ville være i stand til at bruge en streng. Men i dette tilfælde besluttede jeg at bruge FORMAT() funktion til at formatere datoen værdi. Denne funktion konverterer implicit datoen værdi til en streng, og derfor var jeg i stand til at bruge en streng til det andet argument.


  1. Databasebrugerstyring:Håndtering af roller for MariaDB

  2. Sådan udføres rå SQL i SQLAlchemy

  3. Hvordan JSONPath Wildcard Trin (**) fungerer i MariaDB

  4. Indstilling af application_name på Postgres/SQLAlchemy