2009-09-04 1 views
2

Я должен объяснить это на примере:Database дизайн предпочтение: Использование DateTime и BIT в SQL 2000

Есть ли лучшая практика или предпочтения для указания DateTime и БИТ в таблице базы данных?

В моей базе данных У меня есть таблица виджета. Мне нужно знать, является ли виджет «закрытым», и это «Закрытая дата». В бизнес-правилах говорится, что если виджет закрыт, он должен иметь закрытую дату. Если виджет не закрыт, он не должен иметь «Закрытую дату».

Для разработки этого, я мог бы сделать следующее:

(пример 1):

CREATE TABLE [Widget] 
(
    [WidgetID] INT IDENTITY(1,1) 
    ,[ClosedDate] DATETIME NULL 
) 

или (пример 2):

CREATE TABLE [Widget] 
(
    [WidgetID] INT IDENTITY(1,1) 
    ,[IsClosed] BIT NOT NULL CONSTRAINT [DF_Widget_IsClosed] DEFAULT (0) 
    ,[ClosedDate] DATETIME NULL 
) 

Я считаю, что пример 1 чище потому что это одна меньше столбцов, о которых нужно беспокоиться. Но, когда мне нужно оценить, закрыт ли Widget, мне нужен дополнительный шаг, чтобы выяснить, является ли столбец ClosedDate NOT NULL.

Пример 2 создает дополнительные накладные расходы, потому что теперь мне нужно синхронизировать значения IsClosed и ClosedDate.

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

Примечание: Я получаю доступ к этому значению с помощью инструмента ORM, а также хранимых процедур.

+0

сделать «IsClosed» вычисленным столбцом, который является истинным только тогда, когда ClosedDate не является нулевым - см. Ответ JBrooks - дает вам лучшее из обоих сценариев! –

ответ

5

Я думаю, что вариант 1 лучше. Целостность данных лучше сохраняется (невозможно иметь закрытую дату с флагом, который говорит об обратном), занимает меньше места на диске в случае больших больших таблиц, и запросы будут по-прежнему эффективными и понятными для понимания для товарищей по команде.

2

Первый вариант лучше. Проверка нулевого значения является дешевой, тогда как сохранение отдельного флага позволяет закрыть закрытую дату.

0

Я бы не присвоил смысловое значение NULL. Это будет пузыриться через бизнес-логику, и вы получите код, как ...

public class Widget 
{ 
    // stuff 

    public bool IsClosed 
    { 
    // what do you put here? 
    // it was null in the db so you have to use DateTime.MinDate or some such. 
    return(_closeDate == ??); 
    } 

    // more stuff 
} 

Использования нуля в этой моде плохо. NULL (и null) означает «Я не знаю». Вы назначаете семантический смысл этому ответу, когда на самом деле вы не должны. Закрытый статус - закрытое состояние, а закрытая дата - закрытая дата, не скомбинируйте их. (Не дай бог, что вы когда-нибудь захотите снова открыть Виджет, но помните, когда он, например, закрылся, например.)

Эрик Липперт имеет nice blog post об использовании нулевого значения (kidna).

+0

В C# вы используете DateTime? (Nullable ), чтобы соответствовать полю базы данных, так что вы будете делать в этом возвратном выражении. Я не могу сказать, что согласен с вашим советом, потому что он идет против СУХОЙ. –

+2

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

+0

Я тоже не согласен. И в вашем примере вы просто вернете _closeDate.HasValue() (в C#) – Shawson

2

Я думаю, что у вас есть столбец IsClosed в качестве вычисленного столбца.

CREATE TABLE [Widget]( 
[WidgetID] INT IDENTITY(1,1), 
[ClosedDate] DATETIME NULL, 
IsClosed AS CAST(CASE WHEN ClosedDate IS NULL THEN 0 ELSE 1 END AS BIT) 
) 

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

Наконец, при переходе на SQL2005 вы можете добавить предложение «Persisted». Таким образом, он будет храниться, увеличивая производительность немного, и у вас не будет проблемы с синхронизацией.

+0

+1 отлично - мои мысли точно! Один столбец, с которым вы работаете, и вычисленный столбец (который автоматически обновляется), чтобы сигнализировать о состоянии. –

+0

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