如何使视图列NOT NULL


84

我正在尝试创建一个我只希望列为true或false的视图。但是,无论我做什么,SQL Server(2008)似乎都认为我的bit列可以以某种方式为null。

我有一个名为“产品”的表,其“状态”列为INT, NULL。在视图中,我想为Product中的每一行返回一行,如果Product.Status列等于3,则BIT列设置为true,否则位字段应该为false。

示例SQL

SELECT CAST( CASE ISNULL(Status, 0)  
               WHEN 3 THEN 1  
               ELSE 0  
             END AS bit) AS HasStatus  
FROM dbo.Product  

如果我将此查询另存为视图并查看“对象资源管理器”中的列,则HasStatus列设置为BIT, NULL。但是它永远不能为NULL。是否有一些魔术SQL技巧可以用来强制使该列成为NOT NULL

请注意,如果删除CAST()周围的CASE,则该列正确设置为NOT NULL,但是该列的类型设置为INT,这不是我想要的。我希望如此BIT。:-)

Answers:


150

您可以通过重新安排查询来实现所需的目标。诀窍在于,ISNULL必须在外部,SQL Server才能理解结果值永远不可能是NULL

SELECT ISNULL(CAST(
    CASE Status
        WHEN 3 THEN 1  
        ELSE 0  
    END AS bit), 0) AS HasStatus  
FROM dbo.Product  

我真正发现此功能有用的一个原因是使用ORM时,您不希望将结果值映射为可为null的类型。如果您的应用程序认为该值永远不可能为空,则可以使事情变得更加容易。然后,您不必编写代码来处理null异常等。


@Gunder:不用担心,实际上有点奥秘。当在表中创建计算的位列并希望结果不可为空时,这也很方便使用。
RedFilter '02

8
我需要类似的东西,但我发现这COALESCE()ISNULL()
没用

@ EvilBob22这很奇怪,因为COALESCE和ISNULL都可以返回NULL。我猜只是一个编译器怪癖。
RedFilter 2013年

1
这是十亿分之一,用于使EntityFramework在正常情况下不会推断出一个键时推断出一个键。
Erik 2014年


3

仅供参考,对于遇到此消息的人,在强制转换/转换外部添加ISNULL()可能会使您的视图上的优化器混乱。

我们有2个表使用与索引键相同的值,但类型具有不同的数字精度(我知道这很差),并且我们的观点是将它们结合在一起以产生最终结果。但是我们的中间件代码正在寻找一种特定的数据类型,并且该视图在返回的列周围有一个CONVERT()

我注意到,正如OP所做的那样,视图结果的列描述符将其定义为可为空,并且我认为它是2个表上的主键/外键。我们为什么要将结果定义为可为空?

我发现了这篇文章,将ISNULL()放在列周围,瞧-不再可以为null。

问题在于,当查询在该列上进行过滤时,视图的性能直接下降到了厕所。

出于某种原因,视图结果列上的显式CONVERT()不会使优化器搞砸(由于精度不同,它还是不得不这样做),但是添加一个冗余的ISNULL()包装器确实可以方式。


CONVERT()举例说明如何确保/指示不可为空性的解决方案吗?
或Mapper

1
嗨,或者-对不起,我好一阵子没看到这个了。这是一个例子。如果您的视图中有CONVERT(BIT,U.RETIRED),0)AS Retired,则将一个字节或一个int列转换为bit / bool,则它可以为空。通过将ISNULL(CONVERT(BIT,U.RETIRED),0)替换为已退休,可以使视图中的该列不可为空。如果U.RETIRED启动时不为null,则它在功能上除了视图中的列外不会更改任何其他内容。警告:ISNULL()可能会干扰查询优化和索引选择。
user1664043

-3

您在Select语句中所能做的就是控制数据库引擎作为客户端发送给您的数据。select语句对基础表的结构没有影响。要修改表结构,您需要执行Alter Table语句。

  1. 首先,请确保表格中的该位字段当前没有空值
  2. 然后执行以下ddl语句: Alter Table dbo.Product Alter column status bit not null

如果,您想做的只是控制视图的输出,那么您所做的就足够了。您的语法将确保视图结果集中HasStatus列的输出实际上永远不会为null。它始终是位值= 1或位值=0。不用担心对象浏览器会说什么...


6
我不想更改表格列。该列定义为允许为空的整数列。这符合我们的规格。但是我需要一个返回带有位字段的列的视图,该字段不能为null。我知道它不能为null是不够的,该列必须为NOT NULL,这样它才能在我们的ORM中正确映射。
勒内
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.