2016-05-31 55 views
6

运行MS SQL Server 2014 express。突然间,视图中的一列变为空,尽管是两个不可空列的联合。请帮我明白是怎么回事:不可空列的联合可为空

enter image description here

与UNION:

enter image description here

我缺少什么?

编辑更多的信息:当我重新保存IncomingTransactions视图,其列现在变成零,但它不应该!以下是数量列的定义:(CASE PIN.StatusId WHEN 6 THEN PIN.QuantityReceived WHEN 7 THEN 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语句也是面面俱到。即使我将0在ELSE分支中与CAST(0 as decimal(7,2))一起包装,如YB所示,它仍然为空。 CASE没有我想到的语义,或者这是一个错误。

+1

奇怪的部分是Status get'not null',可能取决于数据类型。你是如何创建视图的?我推荐使用两个测试表进行工作,所有数据类型都为空且不为空,并查看是否可以重现此行为 –

+1

您如何使用该视图? WHERE子句?骨料?根据你的查询,你有可能在一个表中有一个不存在于第二个表中的记录,导致使用一个空值。 UNION进行排序并合并以消除重复。如果你想要所有的记录,做一个联盟所有如果你不关心重复,联盟所有更快。 – JVC

+0

@JuanCarlosOropeza,我猜Type,Id,PartTypeId和Status都是关键字段?数量,FiscalYearId,DateTransacted和Source不是。 – Clay

回答

2

几乎每个按照表达式计算的列在SQL Server中都被视为可以为空。解决方法是像你一样使用ISNULL。这是在这里computed columns section

提到的数据库引擎自动确定基于所使用的表达式 计算列的为空。最 表达式的结果被认为是可空即使仅非空列 是本...那是可空的表达可以通过指定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 

为了避免把一个恼人的完全冗余的表达中。

+0

这似乎是Martin的情况,但它没有[记录为这样](https://msdn.microsoft.com/en-us/library/ms181765.aspx?f=255&MSPPError=-2147217396)。 Quote:“如果没有input_expression = when_expression评估为TRUE,则SQL Server数据库引擎在指定ELSE子句时返回else_result_expression,如果未指定ELSE子句,则返回NULL值。”简单和搜索的病例陈述也是如此。在我的示例中,ELSE子句显然不为空。 – naasking

+0

@naasking是的,实际上你的'case'表达式不能返回null。但是很少或根本没有逻辑来分析这一点。几乎任何计算列都将被视为可空,除了包含isnull的列。 –

+1

好的,奇怪的是它并不是在2008 R2中推断出NULL,而是在2014年这样做。我们现在再次检查了这一点,所以看起来MSSQL 2014比2008年的精确度要低。这个答案必须做,谢谢。 – naasking