Relationships and foreign keys
Why BuildMart’s data is spread over five tables, how primary and foreign keys tie them together, and the three kinds of relationship: one-to-many, many-to-many and one-to-one.
| Key | What it is | In BuildMart |
|---|---|---|
Customers.CustomerId, Orders.OrderId | ||
Orders.CustomerId → Customers.CustomerId | ||
OrderItems (OrderId, ProductId) |
Following the keys by hand
SELECT OrderId, CustomerId, OrderDate, Status FROM dbo.Orders WHERE OrderId = 7;SELECT CustomerId, FirstName, LastName, City FROM dbo.Customers WHERE CustomerId = 4;SELECT OrderId, ProductId, Quantity, UnitPrice FROM dbo.OrderItems WHERE OrderId = 7;SELECT ProductId, Name, Price FROM dbo.Products WHERE ProductId IN (4, 8);OrderId CustomerId OrderDate Status
------- ---------- ---------- -------
7 4 2024-05-05 Shipped
CustomerId FirstName LastName City
---------- --------- -------- --------
4 Dev Singh Bradford
OrderId ProductId Quantity UnitPrice
------- --------- -------- ---------
7 4 20 7.00
7 8 5 11.90
ProductId Name Price
--------- ----------------- -----
4 Cement 25 kg 7.20
8 Wood screws (200) 11.90Three kinds of relationship
| Kind | Meaning | How it is built | Example |
|---|---|---|---|
(OrderId, ProductId) stops the same product being listed twice on one order, and the pair is a good place for facts that belong to it, such as Quantity and UnitPrice.
A one-to-one relationship
CREATE TABLE dbo.CustomerLogins ( CustomerId int NOT NULL CONSTRAINT PK_CustomerLogins PRIMARY KEY CONSTRAINT FK_CustomerLogins_Customers REFERENCES dbo.Customers (CustomerId), UserName nvarchar(40) NOT NULL UNIQUE, LastLogin datetime2(0) NULL); INSERT INTO dbo.CustomerLogins (CustomerId, UserName) VALUES (1, N'asha.p');INSERT INTO dbo.CustomerLogins (CustomerId, UserName) VALUES (1, N'asha.second');Msg 2627, Level 14, State 1, Line 10 Violation of PRIMARY KEY constraint 'PK_CustomerLogins'. Cannot insert duplicate key in object 'dbo.CustomerLogins'. The duplicate key value is (1).
Natural or surrogate keys?
Natural values change: people change email address, and every foreign key pointing at the old one would have to change too. A surrogate never needs to. A small intmakes foreign keys and indexes smaller and faster than a long text value.Keep the natural value unique anyway with a UNIQUE constraint, as CustomerLogins does with UserName.
Listing the relationships of a database
SELECT OBJECT_NAME(parent_object_id) AS ChildTable, COL_NAME(parent_object_id, parent_column_id) AS ForeignKey, OBJECT_NAME(referenced_object_id) AS ParentTable, COL_NAME(referenced_object_id, referenced_column_id) AS PointsAtFROM sys.foreign_key_columnsORDER BY ChildTable, ForeignKey;ChildTable ForeignKey ParentTable PointsAt ---------- ---------- ----------- ---------- OrderItems OrderId Orders OrderId OrderItems ProductId Products ProductId Orders CustomerId Customers CustomerId Products CategoryId Categories CategoryId
Show a hint
Show the solution
SELECT CustomerId FROM dbo.Orders WHERE OrderId = 9;SELECT FirstName, LastName FROM dbo.Customers WHERE CustomerId = 2;SELECT ProductId, Quantity FROM dbo.OrderItems WHERE OrderId = 9;SELECT Name FROM dbo.Products WHERE ProductId = 9;CustomerId
----------
2
FirstName LastName
--------- --------
Ben Carter
ProductId Quantity
--------- --------
9 4
Name
----------------
Wall plugs (100)Remember
A primary key identifies each row; a foreign key holds another table’s primary key value and points at one row there. One-to-many: the foreign key goes on the “many” side. Many-to-many: a junction table with two foreign keys and a composite primary key. One-to-one: a foreign key that is also the primary key (or UNIQUE). Surrogate keys (IDENTITY) are the usual choice; keep natural values unique with UNIQUE. Foreign keys are not indexed automatically.