代码之家  ›  专栏  ›  技术社区  ›  René

如何使视图列不为空

  •  72
  • René  · 技术社区  · 16 年前

    我正在尝试创建一个视图,希望列只为true或false。然而,似乎不管我做什么,SQL Server(2008)都相信我的位列可以以某种方式为空。

    我有一个名为“product”的表,其中“status”列是 INT, NULL . 在视图中,我希望为product中的每一行返回一行,如果product.status列等于3,则位列设置为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 . 但它不应该是空的。我能用一些神奇的SQL技巧来强制这个列 NOT NULL .

    注意,如果我移除 CAST() 周围 CASE ,列正确设置为 不为空 ,但该列的类型设置为 INT 这不是我想要的。我希望它是 BIT . -)

    4 回复  |  直到 11 年前
        1
  •  132
  •   D'Arcy Rittich    16 年前

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

        2
  •  3
  •   user1664043    11 年前

    仅供参考,对于遇到此消息的人,在cast/convert的外部添加isNull()可能会破坏视图上的优化器。

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

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

    我找到了这个帖子,把isNull()扔到了列周围,瞧,不能再空了。

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

    出于某种原因,视图结果列上的一个显式convert()并没有破坏优化器(由于精度不同,它无论如何都必须这样做),但是添加了一个冗余的isNull()包装器,在很大程度上做到了这一点。

        3
  •  0
  •   live-love    14 年前

    这是我使用的代码,它将使ID列不为空,而所有其他列都为空。 您必须强制转换bit或varchar列,并将int列与null进行比较。

    CREATE TABLE [dbo].[aTestTable](
        [ID] [int] NOT NULL,
        [varcharCol] [varchar](50) NOT NULL,
        [nullvarcharCol] [varchar](50) NULL,
        [bitCol] [bit] NOT NULL,
        [nullbitCol] [bit] NULL,
        [intCol] [int] NOT NULL,
        [nullintCol] [int] NULL,
     CONSTRAINT [PK_aTestTable] PRIMARY KEY CLUSTERED 
    (
        [ID] ASC
    )WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
    ) ON [PRIMARY]
    
    
    CREATE VIEW [dbo].[aTestView]
    AS
    SELECT  ID ,
            NULLIF(varcharCol , '') AS varcharCol ,
            NULLIF(CAST(varcharCol AS VARCHAR), null) AS varcharCol1, --better
            nullvarcharCol ,
            NULLIF(CAST(bitCol AS INT), null) AS bitCol ,
            nullbitCol ,
            NULLIF(CAST(intCol AS INT), NULL) AS intCol ,
            nullintCol
    FROM    dbo.aTestTable
    
    
    Sample Data:
    
    ID  varcharCol  nullvarcharCol  bitCol  nullbitCol  intCol  nullintCol
    1   1   1   1   1   1   1
    2   0   0   0   0   0   0
    3   0   NULL    0   NULL    0   NULL
    4   a   a   1   1   2   2
    

    高温高压

        4
  •  -1
  •   Charles Bretana    16 年前

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

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

    如果,Otoh,您所要做的就是控制视图的输出,那么您所做的就足够了。您的语法将保证视图结果集中hasstatus列的输出实际上 从未 为空。会的。 总是 位值=1或位值=0。别担心对象资源管理器会说什么…

    推荐文章