SQL Server 2008: что установить FK в качестве PK? - PullRequest
0 голосов
/ 22 декабря 2010

Я собираю свою собственную базу данных, и из примеров, которые я видел, Foriegn Key также можно установить в качестве Первичных ключей.

Я создавал свои таблицы так, чтобы все мои FK были также PK. Это неправильно? Когда ФК должен быть ПК? Это должен быть ПК?

Первичный ключ имеет смысл в их собственной таблице ... как идентификатор и идентичность. Но при использовании Id - это еще одна таблица, это тоже должен быть PK?

Ответы [ 5 ]

4 голосов
/ 22 декабря 2010

Внешний ключ должен быть Первичным ключом только при попытке создать отображение 1 to 1 или 1 to zero/1.

Пример:

У меня есть таблица Person, таблица Employee и таблица Contractor. Все сотрудники - это люди, все подрядчики - это люди, а каждый человек - это сотрудник или подрядчик

По сути, вы бы получили что-то вроде этого.

alt text


В ответ на то, что у ваших людей есть несколько адресов, вы должны создать таблицу ассоциации. Вот схема.

alt text

Как видите, теперь у каждого человека может быть много адресов, и, поскольку каждый Сотрудник - это человек, у каждого Сотрудника может быть много адресов. Это касается и Подрядчика.


Отредактировано: вот сценарий изменения с 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
0 голосов
/ 23 декабря 2010

Одной из ситуаций, когда данный столбец является как PK, так и FK, является реляционная модель для шаблона проектирования gen-spec. В одном из других ответов «Сотрудники» - это специализация «Персоны». PK в таблицах сотрудников ссылается на PK в таблице «Персоны». Таким образом, PK в специализированной таблице также является FK.

Это позволяет создать представление, которое объединяет сотрудников и лиц для предоставления в одном представлении всех данных о сотрудниках, независимо от того, являются ли эти данные специфичными для сотрудников (например, «Дата найма») или общими для всех лиц, независимо от не они сотрудники (например, «Дата рождения»).

Не рекомендуется делать каждый ПК также ФК. ФК должны отражать логическую структуру данных. Если логическая модель нелогична, вы идете к неприятностям.

0 голосов
/ 22 декабря 2010

FK - это поле, указывающее на PK другой таблицы. Вот и все.
Таблица, связанная с самой собой, может содержать FK, указывающий на ее собственный PK.
PK, который также является FK, может иметь место только в дочерней таблице отношения 1: 1.

0 голосов
/ 22 декабря 2010

Существует только один сценарий, который требует, чтобы FK также был PK.

Когда таблица представляет подкласс или подмножество вещей в таблице PK, например, таблицу SalariedEmployees, которая имеет FK для таблицы Employees ...

0 голосов
/ 22 декабря 2010

FK также должен быть PK, только если две таблицы имеют отношение один к одному, а вторая таблица была добавлена, поскольку первая была слишком широкой, и эти элементы не всегда были нужны в большинстве запросов.

Это не сработает вообще, если у вас отношения один-ко-многим или отношения многие-ко-многим.

ФК гораздо чаще не ПК. Если у меня есть личная таблица и связанная таблица адресов, если я сделаю PK и FK одним и тем же, то я могу сохранить только один адрес, но большинство адресных таблиц допускают несколько адресов для одного человека или организации. В этом случае у вас будет и AddressID в качестве PK, и person_id в качестве FK для таблицы person. Это наиболее распространенный сценарий PK / FK.

...