Primary Keys and Foreign Keys in SQL Server: How Tables Actually Connect

Primary Keys and Foreign Keys in SQL Server: How Tables Actually Connect

Everything up to this chapter queried one table at a time. Real schemas are almost never one table — they’re a web of tables connected by keys, and understanding exactly how that connection is enforced (not just “it points to the other table”) is what makes JOINs in the next lesson click instead of feeling like memorized syntax.

Primary & Foreign Keys, connected(how two tables actually link up)Driverdriver_id (PK)full_namecityone row per driverTriptrip_id (PK)driver_id (FK)distance_kmmany rows per driverFK points to a PKINSERT Trip driver_id=999driver_id 999 isn’t in DriverSQL Server rejects itGotcha: deleting aDriver with existingTrips fails by default —no auto-cascade!

Setup — a driver/trip example to follow along:

CREATE TABLE dbo.Driver (
    driver_id   INT IDENTITY(1,1) PRIMARY KEY,
    full_name   NVARCHAR(100) NOT NULL,
    city        NVARCHAR(50)  NOT NULL
);
CREATE TABLE dbo.Trip (
    trip_id       INT IDENTITY(1,1) PRIMARY KEY,
    driver_id     INT NOT NULL REFERENCES dbo.Driver(driver_id),
    distance_km   DECIMAL(6,2) NOT NULL,
    fare_usd      DECIMAL(8,2) NOT NULL
);

The Relationship, Visualized

Driver driver_id (PK) full_name city Trip trip_id (PK) driver_id (FK) distance_km 1-to-many

A primary key (PK) uniquely identifies each row (driver_id in Driver) — SQL Server automatically creates a unique index behind every primary key, which is why lookups by PK are fast by default, before you’ve even thought about indexing. A foreign key (FK) is a column in one table that points to a primary key in another (Trip.driver_idDriver.driver_id).

Watching the Constraint Actually Enforce Something

-- This fails — driver_id 999 doesn't exist in Driver:
INSERT INTO dbo.Trip (driver_id, distance_km, fare_usd) VALUES (999, 5.2, 12.50);
-- Msg 547: The INSERT statement conflicted with the FOREIGN KEY constraint ...

-- This fails too — you can't delete a driver who still has trips referencing them:
INSERT INTO dbo.Driver (full_name, city) VALUES ('Amir Khan', 'Austin');
INSERT INTO dbo.Trip (driver_id, distance_km, fare_usd) VALUES (1, 8.0, 18.00);
DELETE FROM dbo.Driver WHERE driver_id = 1;
-- Msg 547: The DELETE statement conflicted with the REFERENCE constraint ...

This is the entire point of a foreign key: SQL Server enforces that you can’t log a trip for a driver who doesn’t exist, and can’t delete a driver out from under existing trips — it rejects the operation outright, rather than silently leaving a trip pointing at nothing (an “orphaned row”). Without this constraint, that kind of data corruption is entirely possible and often goes unnoticed until a report breaks months later.

Three Relationship Shapes

Shape Example How it’s modeled
One-to-many (1:N) One driver, many trips A foreign key on the “many” side, as shown above
Many-to-many (N:N) Many students enroll in many courses A junction table in between, holding two foreign keys — e.g. Student ↔ Course via Enrollment
One-to-one (1:1) Employee ↔ EmployeeConfidentialDetails A foreign key with a UNIQUE constraint added — rare, often used to split sensitive columns into a separately-secured table

A Many-to-Many Example, Concretely

CREATE TABLE dbo.Student (student_id INT IDENTITY PRIMARY KEY, name NVARCHAR(100) NOT NULL);
CREATE TABLE dbo.Course (course_id INT IDENTITY PRIMARY KEY, title NVARCHAR(100) NOT NULL);

-- The junction table: one row per student-course PAIR, with a composite primary key
CREATE TABLE dbo.Enrollment (
    student_id INT NOT NULL REFERENCES dbo.Student(student_id),
    course_id  INT NOT NULL REFERENCES dbo.Course(course_id),
    enrolled_on DATE NOT NULL DEFAULT GETDATE(),
    PRIMARY KEY (student_id, course_id)
);

Neither Student nor Course has a foreign key pointing directly at the other — they can’t, since either side could relate to many rows on the other. The junction table’s composite primary key (both columns together) also does double duty: it prevents the same student from enrolling in the same course twice.

Practice tip: Sketch the junction table for a “many books can have many authors, many authors can write many books” relationship before the Chapter 7 capstone — you’ll build exactly this schema there for real.

Enjoyed this?

Subscribe to get every new SQL Server lesson as soon as it’s published, and share it with a developer who’d find it useful.

📡 Subscribe via RSS  | 
Share on X  | 
Share on LinkedIn  | 
Share on Facebook

Want the full structured course with quizzes, projects, and 10+ exercises per chapter? Check out SQL Server Fundamentals, coming soon on this site.