Внешний ключ должен быть Первичным ключом только при попытке создать отображение 1 to 1
или 1 to zero/1
.
Пример:
У меня есть таблица Person, таблица Employee и таблица Contractor. Все сотрудники - это люди, все подрядчики - это люди, а каждый человек - это сотрудник или подрядчик
По сути, вы бы получили что-то вроде этого.
В ответ на то, что у ваших людей есть несколько адресов, вы должны создать таблицу ассоциации. Вот схема.
Как видите, теперь у каждого человека может быть много адресов, и, поскольку каждый Сотрудник - это человек, у каждого Сотрудника может быть много адресов. Это касается и Подрядчика.
Отредактировано: вот сценарий изменения с SQL Server
BEGIN TRANSACTION
SET QUOTED_IDENTIFIER ON
SET ARITHABORT ON
SET NUMERIC_ROUNDABORT OFF
SET CONCAT_NULL_YIELDS_NULL ON
SET ANSI_NULLS ON
SET ANSI_PADDING ON
SET ANSI_WARNINGS ON
COMMIT
BEGIN TRANSACTION
GO
CREATE TABLE dbo.Address
(
AddressId bigint NOT NULL,
Address nvarchar(50) NULL,
City nvarchar(50) NULL,
State nvarchar(50) NULL
) ON [PRIMARY]
GO
ALTER TABLE dbo.Address ADD CONSTRAINT
PK_Address PRIMARY KEY CLUSTERED
(
AddressId
) WITH( STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
GO
ALTER TABLE dbo.Address SET (LOCK_ESCALATION = TABLE)
GO
COMMIT
BEGIN TRANSACTION
GO
CREATE TABLE dbo.Person
(
PersonId bigint NOT NULL,
Name nvarchar(50) NULL
) ON [PRIMARY]
GO
ALTER TABLE dbo.Person ADD CONSTRAINT
PK_Person PRIMARY KEY CLUSTERED
(
PersonId
) WITH( STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
GO
ALTER TABLE dbo.Person SET (LOCK_ESCALATION = TABLE)
GO
COMMIT
BEGIN TRANSACTION
GO
CREATE TABLE dbo.PersonAddress
(
PersonId bigint NOT NULL,
AddressId bigint NOT NULL
) ON [PRIMARY]
GO
ALTER TABLE dbo.PersonAddress ADD CONSTRAINT
PK_PersonAddress PRIMARY KEY CLUSTERED
(
PersonId,
AddressId
) WITH( STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
GO
ALTER TABLE dbo.PersonAddress ADD CONSTRAINT
FK_PersonAddress_Person FOREIGN KEY
(
PersonId
) REFERENCES dbo.Person
(
PersonId
) ON UPDATE NO ACTION
ON DELETE NO ACTION
GO
ALTER TABLE dbo.PersonAddress ADD CONSTRAINT
FK_PersonAddress_Address FOREIGN KEY
(
AddressId
) REFERENCES dbo.Address
(
AddressId
) ON UPDATE NO ACTION
ON DELETE NO ACTION
GO
ALTER TABLE dbo.PersonAddress SET (LOCK_ESCALATION = TABLE)
GO
COMMIT
BEGIN TRANSACTION
GO
CREATE TABLE dbo.Employee
(
EmployeeId bigint NOT NULL,
EmployeeNumber nvarchar(50) NULL
) ON [PRIMARY]
GO
ALTER TABLE dbo.Employee ADD CONSTRAINT
PK_Employee PRIMARY KEY CLUSTERED
(
EmployeeId
) WITH( STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
GO
ALTER TABLE dbo.Employee ADD CONSTRAINT
FK_Employee_Person FOREIGN KEY
(
EmployeeId
) REFERENCES dbo.Person
(
PersonId
) ON UPDATE NO ACTION
ON DELETE NO ACTION
GO
ALTER TABLE dbo.Employee SET (LOCK_ESCALATION = TABLE)
GO
COMMIT
BEGIN TRANSACTION
GO
CREATE TABLE dbo.Contractor
(
ContractorId bigint NOT NULL,
ContractorNumber nvarchar(50) NULL
) ON [PRIMARY]
GO
ALTER TABLE dbo.Contractor ADD CONSTRAINT
PK_Contractor PRIMARY KEY CLUSTERED
(
ContractorId
) WITH( STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
GO
ALTER TABLE dbo.Contractor ADD CONSTRAINT
FK_Contractor_Person FOREIGN KEY
(
ContractorId
) REFERENCES dbo.Person
(
PersonId
) ON UPDATE NO ACTION
ON DELETE NO ACTION
GO
ALTER TABLE dbo.Contractor SET (LOCK_ESCALATION = TABLE)
GO
COMMIT