如何使视图列NOT NULL

时间:2010-02-24 14:47:27

标签: sql sql-server-2008 nullable sql-view

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

我有一个名为“Product”的表,其中“Status”列为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。 : - )

3 个答案:

答案 0 :(得分:135)

您可以通过重新安排查询来实现您想要的效果。诀窍是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并且您不希望将结果值映射到可空类型时。如果您的应用程序将值视为永远不为空,那么它可以使事情变得更容易。然后,您不必编写代码来处理空异常等。

答案 1 :(得分:3)

仅供参考,对于遇到此消息的人来说,在强制转换/转换的外部添加ISNULL()可能会使视图中的优化器陷入困境。

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

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

我找到了这篇帖子,把ISNULL()扔到了专栏周围,然后不再可以为空了。

问题是,当在该列上过滤查询时,视图的性能直接降低了。

由于某种原因,视图结果列上的显式CONVERT()没有搞砸优化器(由于精度不同,它无论如何都必须这样做)但添加了冗余的ISNULL()包装器,在很大程度上。

答案 2 :(得分:-2)

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

  1. 首先确保表
  2. 中的该位字段当前没有空值
  3. 然后执行以下ddl语句:  Alter Table dbo.Product Alter column status bit not null
  4. 如果,otoh,你要做的就是控制视图的输出,那么你正在做的就足够了。您的语法将保证视图结果集中HasStatus列的输出实际上从不为空。 总是是位值= 1还是位值= 0.不要担心对象资源管理器会说什么......