naa*_*ing 6 sql sql-server sql-server-2014-express
运行MS SQL server 2014 express.突然之间,视图中的一个列变为可空,尽管它是两个不可为空的列的并集.请帮我理解这里发生了什么:
和UNION:
我错过了什么?
编辑更多信息:当我重新保存IncomingTransactions视图时,它的列现在变为null,但它不应该是!以下是数量列的定义:( CASE PIN.StatusId WHEN 6那么PIN.QuantityReceived在7,然后0 ELSE PIN.QuantityRevised END)AS数量.每个数量字段都是非空的,并且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
Run Code Online (Sandbox Code Playgroud)
即使case语句是详尽的,ybTest1视图中的Q列也为null.即使我在ELSE分支中包含0 CAST(0 as decimal(7,2)),如YB所示,它仍然是空的.CASE没有我认为的语义,或者这是一个bug.
在 SQL Server 中,作为表达式结果计算的几乎每一列都被视为可为空。解决方法是像您一样使用 ISNULL。此处的 计算列部分提到了这一点
数据库引擎根据所使用的表达式自动确定计算列的可为空性。即使仅存在不可为空的列,大多数表达式的结果也被视为可为空...可通过指定 可以将可为空的表达式转换为不可为空的表达式
ISNULL(check_expression, constant),其中常量是替换任何空结果的非空值。
但它适用于作为计算结果派生列的任何地方,包括在视图定义中。
几乎没有或根本没有逻辑来分析 null 是否实际上可能(有时比看起来更困难,因为各种已弃用的设置选项可能会引发 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
Run Code Online (Sandbox Code Playgroud)
和
Create View ybTestNSB As
Select ISNULL(CASE X WHEN 0 THEN Q1 END, 0) AS Q From ybTest1
Run Code Online (Sandbox Code Playgroud)
为了避免在那里放置一个令人讨厌的完全多余的表达式。