Я бы хотел еще больше упростить этот подход. Вместо 3 таблиц, определяющих коды (Code, CodeKey и CodeValue), как насчет одной таблицы, которая содержит как типы кодов, так и значения кодов? Ведь типы кодов - это просто другой список кодов.
Возможно определение таблицы примерно так:
CREATE TABLE [dbo].[Code](
[CodeType] [int] NOT NULL,
[Code] [int] NOT NULL,
[CodeDescription] [nvarchar](40) NOT NULL,
[CodeAbreviation] [nvarchar](10) NULL,
[DateEffective] [datetime] NULL,
[DateExpired] [datetime] NULL,
CONSTRAINT [PK_Code] PRIMARY KEY CLUSTERED
(
[CodeType] ASC,
[Code] ASC
)
GO
Может быть корневая запись с CodeType = 0, Code = 0, которая представляет тип для CodeType. Все записи CodeType будут иметь CodeType = 0 и Code> = 1. Вот некоторые примеры данных, которые могут помочь прояснить ситуацию:
SELECT CodeType, Code, Description FROM Code
Results:
CodeType Code Description
-------- ---- -----------
0 0 Type
0 1 Gender
0 2 Hair Color
1 1 Male
1 2 Female
2 1 Blonde
2 2 Brunette
2 3 Redhead
В таблицу кодов можно добавить проверочное ограничение, чтобы убедиться, что в таблицу введен действительный кодовый тип:
ALTER TABLE [dbo].[Code] WITH CHECK ADD CONSTRAINT [CK_Code_CodeType]
CHECK (([dbo].[IsValidCodeType]([CodeType])=(1)))
GO
Функция IsValidCodeType может быть определена так:
CREATE FUNCTION [dbo].[IsValidCodeType]
(
@Code INT
)
RETURNS BIT
AS
BEGIN
DECLARE @Result BIT
IF EXISTS(SELECT * FROM dbo.Code WHERE CodeType = 0 AND Code = @Code)
SET @Result = 1
ELSE
SET @Result = 0
RETURN @Result
END
GO
Одна из поднятых проблем состоит в том, как обеспечить, чтобы таблица с столбцом кода имела правильное значение для этого типа кода. Это также может быть обеспечено проверочным ограничением с использованием функции.
Вот таблица Person, в которой есть столбец пола. Рекомендуется присваивать имена всем столбцам кода с описанием типа кода (в данном примере «Пол»), за которым следует слово «Код»:
CREATE TABLE [dbo].[Person](
[PersonID] [int] IDENTITY(1,1) NOT NULL,
[LastName] [nvarchar](40) NULL,
[FirstName] [nvarchar](40) NULL,
[GenderCode] [int] NULL,
CONSTRAINT [PK_Person] PRIMARY KEY CLUSTERED ([PersonID] ASC)
GO
ALTER TABLE [dbo].[Person] WITH CHECK ADD CONSTRAINT [CK_Person_GenderCode]
CHECK (([dbo].[IsValidCode]('Gender',[Gendercode])=(1)))
GO
IsValidCode можно определить следующим образом:
CREATE FUNCTION [dbo].[IsValidCode]
(
@CodeTypeDescription NVARCHAR(40),
@Code INT
)
RETURNS BIT
AS
BEGIN
DECLARE @CodeType INT
DECLARE @Result BIT
SELECT @CodeType = Code
FROM dbo.Code
WHERE CodeType = 0 AND CodeDescription = @CodeTypeDescription
IF (@CodeType IS NULL)
BEGIN
SET @Result = 0
END
ELSE
BEGiN
IF EXISTS(SELECT * FROM dbo.Code WHERE CodeType = @CodeType AND Code = @Code)
SET @Result = 1
ELSE
SET @Result = 0
END
RETURN @Result
END
GO
Может быть создана другая функция для предоставления описания кода при запросе таблицы, в которой есть столбец кода. Вот
Пример запроса таблицы Person:
SELECT PersonID,
LastName,
FirstName,
GetCodeDescription('Gender',GenderCode) AS Gender
FROM Person
Все это задумывалось с точки зрения предотвращения распространения справочных таблиц в базе данных и предоставления одной справочной таблицы. Я понятия не имею, будет ли этот дизайн хорошо работать на практике.