Проектирование базы данных. Как обеспечить соблюдение ограничения внешнего ключа для таблицы с помощью суррогатного ключа

StackOverflow https://stackoverflow.com/questions/3828359

Вопрос

Моя схема таблицы выглядит примерно так

1.Главный стол:Пункт

Столбцы

  1. ClauseID = суррогатный ПК (идентификатор)
  2. ClauseCode = значение, указанное пользователем nvarchar
  3. Class = nvarchar FK в таблицу мастер-классов
  4. и т. д...

ClauseCode + Class = потенциальный ключ для этой таблицы.

2.Главный стол:Групповое предложение

Столбцы

  1. GroupClauseID = суррогатный ПК (идентификатор)
  2. GroupClauseCode = указанное пользователем значение nvarchar
  3. Class = nvarchar fk в таблицу мастер -класса и т. Д.

GroupClauseCode + Class = ключ-кандидат для этой таблицы.

3.Таблица транзакций/сопоставлений ::GroupClause_Clause_Mapping :эта таблица сопоставляет каждое групповое предложение с несколькими отдельными предложениями

Столбцы

  1. GroupClauseID = FK для GroupClause PK
  2. ClauseID = FK к пункту PK
  3. и т. д...

Требование: Предложения каждой группы могут быть сопоставлены только с предложениями, принадлежащими к тому же классу, что и она сама.

Проблема :Приведенная выше конструкция таблицы не обеспечивает соблюдение этого требования на уровне БД.

Одно из возможных решений: Таблица *GroupClause_Clause_Mapping* содержит столбцы.

  1. Код статьи
  2. ГруппаКодКод
  3. Сорт

При этом я могу создавать класс ClauseCode + как таблица FK для предложения, а также GroupClauseCode + Class As FK для таблицы GroupClause.

Однако, если я сделаю это таким образом, тогда суррогатные идентификационные ключи бесполезны, и я могу от них избавиться.

Есть ли проблема с моим дизайном, использующим суррогатные ключи?

Есть какие-нибудь предложения относительно того, как я могу использовать суррогатные ключи и при этом обеспечивать соблюдение ограничений на уровне БД?

Это было полезно?

Решение

Если сами коды большие/громоздкие, вы все равно можете использовать их суррогаты, если они доступны.

Поскольку вы хотите обеспечить только соответствие классов, ваша таблица сопоставления может быть

ClauseID,
GroupClauseID,
Class (or possibly ClassID)

Для ваших главных таблиц все равно будет PK (ClauseID) и уникальное ограничение (ClauseID, Class).Затем вы можете решить, использовать ли только FK (ClauseID,Class) или иметь два FK между таблицей сопоставления и каждой главной таблицей (фактически, тогда вы бы сказали, что один FK является ссылкой на внешний ключ, а другой предназначен для соблюдайте свои правила).

У меня есть аналогичная настройка в одной из моих баз данных (например, в системе опросов):

CREATE TABLE [dbo].[DataItems](
    [DataItemID] [uniqueidentifier] ROWGUIDCOL  NOT NULL,
    [TypeRequired] [varchar](10) NOT NULL,
    [Name] [varchar](50) NOT NULL,
    /* Other Columns */
 CONSTRAINT [PK_DataItems] PRIMARY KEY NONCLUSTERED 
(
    [DataItemID] ASC
),
 CONSTRAINT [UX_DataItems_ClientAnswerFKTarget] UNIQUE CLUSTERED 
(
    [DataItemID] ASC,
    [TypeRequired] ASC
),
 CONSTRAINT [UX_DataItems_Name] UNIQUE NONCLUSTERED 
(
    [Name] ASC
)
)

CREATE TABLE [dbo].[ClientAnswers](
    [ClientAnswersID] [uniqueidentifier] ROWGUIDCOL  NOT NULL,
    [ClientID] [uniqueidentifier] NOT NULL,
    [DataItemID] [uniqueidentifier] NOT NULL,
    [TypeRequired] [varchar](10) NOT NULL,
    [BoolValue] [bit] NULL,
    [IntValue] [int] NULL,
    [CharValue] [varchar](6500) NULL,
    [CurrencyValue] [int] NULL,
    [DateValue] [datetime] NULL,
    /* Other Columns */
 CONSTRAINT [PK_ClientAnswers] PRIMARY KEY CLUSTERED 
(
    [ClientID] ASC,
    [DataItemID] ASC
)
)
GO
ALTER TABLE [dbo].[ClientAnswers] ADD  CONSTRAINT [FK_ClientAnswers_DataItems] FOREIGN KEY([DataItemID],)
REFERENCES [dbo].[DataItems] ([DataItemID])
ON UPDATE CASCADE
GO
ALTER TABLE [dbo].[ClientAnswers] ADD  CONSTRAINT [FK_ClientAnswers_DataItems_TypesMatch] FOREIGN KEY([DataItemID],TypeRequired)
REFERENCES [dbo].[DataItems] ([DataItemID],TypeRequired)
GO

А затем я иду дальше и получаю больше ограничений, гарантирующих, что столбец типа соответствует ненулевому столбцу *Value.

Другие советы

«Если я сделаю это таким образом, то суррогатные идентификационные ключи будут бесполезны, и мне придется от них избавиться».

Правильно.Это одна из причин использования естественных ключей вместо суррогатных:когда вам нужно реализовать какое-то дополнительное ограничение или логику, используя значения естественных ключей.

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top