Более хороший способ написать CHECK CONSTRAINT, который проверяет, что ровно одно значение не равно NULL - PullRequest
5 голосов
/ 24 августа 2011

Представьте, что у меня есть таблица с целочисленными столбцами Col1, Col2, Col3, Col4. Каждый столбец имеет значение NULL и допустимая строка должна содержать значение ровно в 1 столбце (т. Е. Все значения NULL недействительны, а более 1 столбца также недопустимы).

На данный момент у меня есть проверочное ограничение, подобное этому

ALTER TABLE [dbo].[MyTable]  WITH CHECK 
    ADD CONSTRAINT [CK_ReportTemplateAttributes] CHECK  
    ((
        [Col1] IS NOT NULL AND [Col2] IS NULL AND [Col3] IS NULL AND [Col4] IS NULL
        OR 
        [Col1] IS NULL AND [Col2] IS NOT NULL AND [Col3] IS NULL AND [Col4] IS NULL
        OR 
        [Col1] IS NULL AND [Col2] IS NULL AND [Col3] IS NOT NULL AND [Col4] IS NULL
        OR 
        [Col1] IS NULL AND [Col2] IS NULL AND [Col3] IS NULL AND [Col4] IS NOT NULL
    ));
GO;

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

Ответы [ 2 ]

9 голосов
/ 24 августа 2011

Чтобы напомнить другой ответ здесь, я думаю, что это немного более самодокументировано:

ALTER TABLE [dbo].[MyTable]  WITH CHECK 
ADD CONSTRAINT [CK_ReportTemplateAttributes] CHECK  
(1 = CASE when [Col1] IS NULL THEN 0 ELSE 1 END + 
     CASE when [Col2] IS NULL THEN 0 ELSE 1 END + 
     CASE when [Col3] IS NULL THEN 0 ELSE 1 END + 
     CASE when [Col4] IS NULL THEN 0 ELSE 1 END ) ;

Преимущество также состоит в том, что вы можете избежать ошибки, когда вы изменяете ограничение, чтобы учитывать другой столбец, но забыли обновить значение «3» до «[количество столбцов в ограничении] - 1».

7 голосов
/ 24 августа 2011

Самый краткий способ, который я могу себе представить на данный момент:

ALTER TABLE [dbo].[MyTable]  WITH CHECK 
ADD CONSTRAINT [CK_ReportTemplateAttributes] CHECK  
(3 = ISNULL([Col1] - [Col1],1) + 
     ISNULL([Col2] - [Col2],1) + 
     ISNULL([Col3] - [Col3],1) + 
     ISNULL([Col4] - [Col4],1)) ;
...