88

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

我有一个名为“产品”的表,其中的“状态”列是INT, NULL. 在一个视图中,我想为 Product 中的每一行返回一行,如果 Product.Status 列等于 3,则 BIT 列设置为 true,否则 bit 字段应该为 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。:-)

4

3 回答 3

154

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

于 2010-02-24T15:08:18.533 回答
5

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

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

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

我找到了这篇文章,将 ISNULL() 扔到了列周围,瞧——不再可以为空了。

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

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

于 2015-01-14T20:22:08.260 回答
-3

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

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

如果你想要做的只是控制视图的输出,那么你所做的就足够了。您的语法将保证视图结果集中 HasStatus 列的输出实际上永远不会为空。它总是位值 = 1 或位值 = 0。不要担心对象资源管理器说什么......

于 2010-02-24T14:54:24.690 回答