Представление SQL выводит столбец, допускающий значение NULL, из таблицы, отличной от NULL?

У меня есть таблица Product с ненулевыми столбцами «количество» (десятичное число) и «статус» (int), и я создал представление этой таблицы со следующим выражением case:

SELECT P.ProductTypeId,
       (CASE WHEN P.StatusId IN (5, 8) THEN 0 ELSE -P.Quantity END) AS Quantity,
       ...
FROM Product P

ProductTypeId правильно выводится как ненулевой. Однако столбец Quantity этого представления выводится как обнуляемый, даже если базовые столбцы не допускают обнуления. Это не имеет для меня никакого смысла.

Я мог бы использовать ISNULL/COALESCE, чтобы предоставить значение по умолчанию в этом случае и обеспечить необнуляемость, но значимого значения по умолчанию нет, и это не должно происходить в первую очередь, насколько я понимаю. Есть идеи, что происходит?


person naasking    schedule 17.05.2011    source источник
comment
Возможный дубликат Как сделать столбец представления NOT NULL   -  person Ian Kemp    schedule 28.03.2019


Ответы (1)


Приведенное ниже объяснение относится к вычисляемым столбцам в таблице. Я предполагаю, что то же самое относится к вычисляемым столбцам в представлении.

Компонент Database Engine автоматически определяет допустимость значений NULL для вычисляемых столбцов на основе используемых выражений. Результат большинства выражений считается допускающим значение NULL, даже если присутствуют только столбцы, не допускающие значения NULL, поскольку возможные потери значимости или переполнения также приведут к нулевым результатам. Используйте функцию COLUMNPROPERTY со свойством AllowsNull, чтобы исследовать допустимость значений NULL для любого вычисляемого столбца в таблице. Выражение, допускающее значение NULL, можно превратить в не допускающее значение NULL, указав ISNULL (выражение_проверки, константа), где константа представляет собой ненулевое значение, заменяющее любой нулевой результат.

Пример, когда ваше выражение может вернуть NULL, это

SET ARITHABORT OFF;
SET ANSI_WARNINGS OFF;

WITH Product(Quantity,StatusId) As
(
SELECT -2147483648,1
)
SELECT (CASE WHEN P.StatusId IN (5, 8) THEN 0 ELSE -P.Quantity END) AS Quantity  
FROM Product P
person Martin Smith    schedule 17.05.2011
comment
И никак нельзя указать, что этот случай переполнения невозможен? - person naasking; 17.05.2011