Jeśli używasz nazwiska osoby jako klucza podstawowego, a jej nazwisko się zmieniło, musisz zmienić klucz podstawowy. To jest to, co ON UPDATE CASCADE
służy do ponieważ zasadniczo kaskadach puch zmianę do wszystkich powiązanych tabel, które mają zagranicznych kluczowych relacji do klucza podstawowego.
Na przykład:
USE tempdb;
GO
CREATE TABLE dbo.People
(
PersonKey VARCHAR(200) NOT NULL
CONSTRAINT PK_People
PRIMARY KEY CLUSTERED
, BirthDate DATE NULL
) ON [PRIMARY];
CREATE TABLE dbo.PeopleAKA
(
PersonAKAKey VARCHAR(200) NOT NULL
CONSTRAINT PK_PeopleAKA
PRIMARY KEY CLUSTERED
, PersonKey VARCHAR(200) NOT NULL
CONSTRAINT FK_PeopleAKA_People
FOREIGN KEY REFERENCES dbo.People(PersonKey)
ON UPDATE CASCADE
) ON [PRIMARY];
INSERT INTO dbo.People(PersonKey, BirthDate)
VALUES ('Joe Black', '1776-01-01');
INSERT INTO dbo.PeopleAKA(PersonAKAKey, PersonKey)
VALUES ('Death', 'Joe Black');
SELECT
Przeciwko obu tabelach:
SELECT *
FROM dbo.People p
INNER JOIN dbo.PeopleAKA pa ON p.PersonKey = pa.PersonKey;
Zwroty:
Jeśli zaktualizujemy PersonKey
kolumnę i ponownie uruchom SELECT
:
UPDATE dbo.People
SET PersonKey = 'Mr Joe Black'
WHERE PersonKey = 'Joe Black';
SELECT *
FROM dbo.People p
INNER JOIN dbo.PeopleAKA pa ON p.PersonKey = pa.PersonKey;
widzimy:
Patrząc na plan powyższej UPDATE
instrukcji, wyraźnie widzimy, że obie tabele są aktualizowane za pomocą pojedynczej instrukcji aktualizacji na podstawie klucza obcego zdefiniowanego jakoON UPDATE CASCADE
:
kliknij obraz powyżej, aby zobaczyć go bardziej wyraziście
Na koniec wyczyścimy nasze tabele tymczasowe:
DROP TABLE dbo.PeopleAKA;
DROP TABLE dbo.People;
Preferowany 1 sposobem na wykonanie tego przy użyciu kluczy zastępczych byłoby:
USE tempdb;
GO
CREATE TABLE dbo.People
(
PersonID INT NOT NULL IDENTITY(1,1)
CONSTRAINT PK_People
PRIMARY KEY CLUSTERED
, PersonName VARCHAR(200) NOT NULL
, BirthDate DATE NULL
) ON [PRIMARY];
CREATE TABLE dbo.PeopleAKA
(
PersonAKAID INT NOT NULL IDENTITY(1,1)
CONSTRAINT PK_PeopleAKA
PRIMARY KEY CLUSTERED
, PersonAKAName VARCHAR(200) NOT NULL
, PersonID INT NOT NULL
CONSTRAINT FK_PeopleAKA_People
FOREIGN KEY REFERENCES dbo.People(PersonID)
ON UPDATE CASCADE
) ON [PRIMARY];
INSERT INTO dbo.People(PersonName, BirthDate)
VALUES ('Joe Black', '1776-01-01');
INSERT INTO dbo.PeopleAKA(PersonID, PersonAKAName)
VALUES (1, 'Death');
SELECT *
FROM dbo.People p
INNER JOIN dbo.PeopleAKA pa ON p.PersonID = pa.PersonID;
UPDATE dbo.People
SET PersonName = 'Mr Joe Black'
WHERE PersonID = 1;
Dla kompletności plan instrukcji aktualizacji jest bardzo prosty i wykazuje jedną zaletę zastępowania kluczy, mianowicie tylko jeden wiersz wymaga aktualizacji, a nie każdy wiersz zawierający klucz w scenariuszu z kluczem naturalnym:
SELECT *
FROM dbo.People p
INNER JOIN dbo.PeopleAKA pa ON p.PersonID = pa.PersonID;
DROP TABLE dbo.PeopleAKA;
DROP TABLE dbo.People;
Dane wyjściowe z dwóch SELECT
powyższych instrukcji są następujące:
Zasadniczo wynik jest w przybliżeniu taki sam. Jedną z głównych różnic jest to, że szeroki naturalny klucz nie jest powtarzany w każdej tabeli, w której występuje klucz obcy. W moim przykładzie używam VARCHAR(200)
kolumny do przechowywania nazwiska osoby, co wymaga użycia znakuVARCHAR(200)
wszędzie . Jeśli istnieje wiele wierszy i wiele tabel zawierających klucz obcy, spowoduje to powstanie dużej ilości zmarnowanej pamięci. Uwaga: nie mówię o marnowaniu miejsca na dysku, ponieważ większość ludzi twierdzi, że miejsce na dysku jest tak tanie, że jest zasadniczo wolne. Pamięć jest jednak droga i zasługuje na pielęgnację. Użycie 4-bajtowej liczby całkowitej dla klucza pozwoli zaoszczędzić dużo pamięci, biorąc pod uwagę średnią długość nazwy wynoszącą około 15 znaków.
Styczne z pytaniem o to, jak i dlaczego klucze mogą się zmieniać, jest pytanie o to, dlaczego wybierać klucze naturalne zamiast kluczy zastępczych, co jest interesującym i być może ważniejszym pytaniem, szczególnie tam, gdzie wydajność jest celem projektowym. Zobacz moje pytanie tutaj na ten temat.
1 - http://weblogs.sqlteam.com/mladenp/archive/2009/10/06/Why-I-prefer-surrogate-keys-instead-of-natural-keys-in.aspx