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

我有一个名为“产品”的表,其中“状态”列是 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. :-)

有帮助吗?

解决方案

您可以实现你想要通过重新排列查询有点什么。的诀窍在于,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 和你不要映射到一个空类型所得到的值。如果你的应用程序看到的价值永远不可能被空它可以使事情变得更容易各地。然后,你不必编写代码来处理空异常等。

其他提示

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

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

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

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

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

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

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

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

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

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top