运行MS SQL server 2014 express。突然之间,视图中的一个列变为可空,尽管它是两个不可为空的列的并集。请帮助我理解这里发生了什么:
和UNION:
我错过了什么?
使用更多信息进行编辑:当我重新保存IncomingTransactions视图时,其列现在变为空,但它不应该是!这里是数量列的定义:( CASE PIN.StatusId WHEN 6那个PIN.QuantityReceived 7,然后0 ELSE PIN.QuantityRevised END)AS Quantity。每个数量字段都是非空的,并且case语句是详尽的。查询的其余部分是StatusId字段上的简单连接,这是一个非空的FK,所以我仍然在这里丢失。
编辑2:根据以下YB的建议,我创建了一个重现此行为的最小测试用例:
Create Table ybTest1 (Q1 decimal (7,2) not null, X int not null);
GO
Create View ybTestNSB As
Select (CASE X WHEN 0 THEN Q1 ELSE CAST(0 as decimal(7,2)) END) AS Q From ybTest1
GO
ybTest1视图中的Q列为空,即使case语句是详尽的。即使我用CAST(0 as decimal(7,2))
将{0}封装在ELSE分支中,如YB所示,它仍然为空。 CASE没有我认为的语义,或者这是一个错误。
答案 0 :(得分:2)
几乎每个由于表达式而计算的列在SQL Server中都被视为可为空。解决方法是使用ISNULL。 computed columns section此处
中提到了这一点数据库引擎自动确定可空性 根据使用的表达式计算列。结果最多 即使只有不可为空的列,表达式也被认为是可空的 存在...可以为空的表达式可以变成a 通过指定
ISNULL(check_expression, constant)
,不可为空的, 其中常量是替换任何空结果的非空值。
但它适用于作为计算结果导出列的任何位置,包括在视图定义中。
很少或没有逻辑来分析空值是否实际可行(有时比看起来更困难,因为各种已弃用的set选项可能会导致null而不是溢出错误,因此即使1 + X
在您的示例中也可能产生null)它在谨慎方面犯了错误。我认为你的case
表达式无法在现实中输出null
,但根据我的经验,除isnull
中包含的列外,任何计算列都将被视为可为空。
因此,在您的测试用例中,您可以替换
Create View ybTestNSB As
Select (CASE X WHEN 0 THEN Q1 ELSE CAST(0 as decimal(7,2)) END) AS Q From ybTest1
用
Create View ybTestNSB As
Select ISNULL(CASE X WHEN 0 THEN Q1 END, 0) AS Q From ybTest1
为了避免在那里放置一个烦人的完全多余的表达。