Якщо ви використовували ім'я людини в якості основного ключа, а їх ім’я змінилося, вам потрібно буде змінити первинний ключ. Це те ON UPDATE CASCADE
, для чого використовується, оскільки воно по суті каскадує зміни до всіх пов'язаних таблиць, які мають зовнішні ключові зв'язки до первинного ключа.
Наприклад:
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
проти обох таблиць:
SELECT *
FROM dbo.People p
INNER JOIN dbo.PeopleAKA pa ON p.PersonKey = pa.PersonKey;
Повернення:
Якщо ми оновимо PersonKey
стовпець і повторно запустимо 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;
ми бачимо:
Дивлячись на план вищесказаного UPDATE
твердження, ми чітко бачимо, що обидві таблиці оновлюються одним твердженням оновлення в силу зовнішнього ключа, визначеного як ON UPDATE CASCADE
:
клацніть на зображенні вище, щоб побачити його більш чітко
Нарешті, ми очистимо наші тимчасові таблиці:
DROP TABLE dbo.PeopleAKA;
DROP TABLE dbo.People;
Кращий 1 способом зробити це за допомогою сурогатних ключів буде:
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;
Для повноти план оператора оновлення дуже простий і показує одну перевагу сурогатних ключів, а саме лише один рядок потрібно оновлювати на відміну від кожного рядка, що містить ключ у сценарії з природним ключем:
SELECT *
FROM dbo.People p
INNER JOIN dbo.PeopleAKA pa ON p.PersonID = pa.PersonID;
DROP TABLE dbo.PeopleAKA;
DROP TABLE dbo.People;
Вихід із двох SELECT
вищезазначених тверджень:
По суті, результат приблизно однаковий. Одна з головних відмінностей полягає в тому, що широкий природний ключ повторюється не в кожній таблиці, де відбувається зовнішній ключ. У своєму прикладі я використовую VARCHAR(200)
стовпець, щоб утримувати ім’я людини, що вимагає використання VARCHAR(200)
скрізь . Якщо рядок і багато таблиць, що містять зовнішній ключ, це додасть до великої кількості марної пам'яті. Зауважте, я не кажу про те, що місце на диску витрачається даремно, оскільки більшість людей кажуть, що місце на диску є таким дешевим, що бути фактично вільним. Пам’ять, однак, дорога і заслуговує на дорогу. Використання 4-байтового цілого числа для ключа дозволить заощадити великий об'єм пам'яті, якщо врахувати середню довжину імені близько 15 символів.
Дотичне до питання про те, як і чому можуть змінюватися ключі, - це питання про те, чому обирати природні ключі над сурогатними ключами, що є цікавим і, мабуть, більш важливим питанням, особливо, коли продуктивність є ціллю дизайну. Дивіться моє запитання тут цього приводу.
1 - http://weblogs.sqlteam.com/mladenp/archive/2009/10/06/Why-I-prefer-surrogate-keys-instead-of-natural-keys-in.aspx