หากคุณใช้ชื่อของบุคคลเป็นคีย์หลักและเปลี่ยนชื่อคุณจะต้องเปลี่ยนคีย์หลัก นี่คือสิ่งที่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');
A 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 1