Я занимаюсь разработкой базы данных SQL Server 2012, и у меня есть вопрос об отношении «один к одному».
У меня есть две таблицы, Codes
и HelperCodes
. Код может иметь ноль или один вспомогательный код. Это скрипт sql для создания этих двух таблиц и их взаимосвязей:
CREATE TABLE [dbo].[Code]
(
[Id] NVARCHAR(20) NOT NULL,
[Level] TINYINT NOT NULL,
[CommissioningFlag] TINYINT NOT NULL,
[SentToRanger] BIT NOT NULL DEFAULT 0,
[LastChange] NVARCHAR(50) NOT NULL,
[UserName] NVARCHAR(50) NOT NULL,
[Source] NVARCHAR(50) NOT NULL,
[Reason] NVARCHAR(200) NULL,
[HelperCodeId] NVARCHAR(20) NULL,
CONSTRAINT [PK_Code] PRIMARY KEY CLUSTERED
(
[Id] ASC
),
CONSTRAINT [FK_Code_LevelConfiguration]
FOREIGN KEY ([Level])
REFERENCES [dbo].[LevelConfiguration] ([Level]),
CONSTRAINT [FK_Code_HelperCode]
FOREIGN KEY ([HelperCodeId])
REFERENCES [dbo].[HelperCode] ([HelperCodeId])
)
CREATE TABLE [dbo].[HelperCode]
(
[HelperCodeId] NVARCHAR(20) NOT NULL,
[Level] TINYINT NOT NULL,
[CommissioningFlag] TINYINT NOT NULL,
[LastChange] NVARCHAR(50) NOT NULL,
CONSTRAINT [PK_HelperCode] PRIMARY KEY CLUSTERED
(
[HelperCodeId] ASC
),
CONSTRAINT [FK_HelperCode_LevelConfiguration]
FOREIGN KEY ([Level])
REFERENCES [dbo].[LevelConfiguration] ([Level])
)
Это верно?
Код и HelperCode - это разные сущности. HelperCode может быть использован (ни один Код не ссылается на него), или используется (только один Код ссылается на него).
Возможно Code.HelperCodeId должен быть частью первичного ключа таблицы кодов. Но я не уверен, что нулевой столбец может быть частью первичного. Делая это, я хочу, чтобы два или более кодов ссылались на один и тот же HelperCode.
database-design
sql-server-2012
VansFannel
источник
источник
HelperCodeId
быть частью ПК? Это случайно не потому, что вы хотите запретить двум или более кодам ссылаться на один и тот же HelperCode?HelperCodeId
столбец как уникальный.Ответы:
Чтобы ответить на вопрос в заголовке, нет, все основные столбцы должны быть
NOT NULL
.Но не изменяя структуру таблиц, вы можете добавить отфильтрованный индекс к
Code (HelperCodeId)
столбцу:Фильтр (
WHERE HelperCodeId IS NOT NULL
) необходим из-за того, как SQL-Server обрабатывает пустые значения в уникальных ограничениях и уникальных индексах Без фильтра SQL-сервер не позволил бы более одной строки сNULL
inHelperCodeId
.Альтернативным дизайном будет удаление
HelperCodeId
изCode
и добавление третьей таблицы, в которой будут храниться отношенияCode
-HelperCode
. Взаимосвязь между двумя объектами выглядит как «ноль или один-один-ноль-один» (оба кода могут не иметь HelperCode, а HelperCode может не использоваться никаким кодом):HelperCode
остается неизменной:Дополнительная таблица будет иметь два
UNIQUE
ограничения (или одно основное и одно уникальное), чтобы гарантировать, что каждый код связан с (максимум) одним HelperCode, а каждый код HelperCode связан с (максимум) одним кодом. Оба столбца будутNOT NULL
:источник
Попробуйте вместо этого использовать уникальное ограничение. Возможно, стандарт ANSI объявил нулевые значения в качестве первичного ключа недействительными, но я никогда не видел стандарт и не хочу его покупать, чтобы это проверить.
Отсутствие нулевых ключей, кажется, является одной из тех вещей, в которую разработчики очень твердо верят, так или иначе. Я предпочитаю использовать их, потому что я считаю, что это полезно для справочных таблиц, содержащих всплывающие подсказки и связанные данные для выпадающих списков, которые не были заполнены.
Меня учили, что нулевое значение указывает, что переменная никогда не была установлена, а пустое значение указывает, что значение было установлено в прошлом. Конечно, это зависит от разработчика, чтобы определить для приложения, но я считаю бессмысленным разрешать пустые первичные ключи, но не нулевые первичные ключи.
источник