如何使视图列不为空

发布于 2024-08-22 18:25:36 字数 714 浏览 12 评论 0原文

我正在尝试创建一个视图,其中我希望列仅为 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

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

I'm trying to create a view where I want a column to be only true or false. However, it seems that no matter what I do, SQL Server (2008) believes my bit column can somehow be null.

I have a table called "Product" with the column "Status" which is INT, NULL. In a view, I want to return a row for each row in Product, with a BIT column set to true if the Product.Status column is equal to 3, otherwise the bit field should be false.

Example SQL

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

If I save this query as a view and look at the columns in Object Explorer, the column HasStatus is set to BIT, NULL. But it should never be NULL. Is there some magic SQL trick I can use to force this column to be NOT NULL.

Notice that, if I remove the CAST() around the CASE, the column is correctly set as NOT NULL, but then the column's type is set to INT, which is not what I want. I want it to be BIT. :-)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

寄离 2024-08-29 18:25:36

您可以通过稍微重新安排查询来实现您想要的结果。诀窍在于,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 时,您不希望得到结果映射到可为空类型的值。如果您的应用程序认为该值永远不可能为空,那么一切都会变得更容易。那么你就不必编写代码来处理空异常等。

You can achieve what you want by re-arranging your query a bit. The trick is that the ISNULL has to be on the outside before SQL Server will understand that the resulting value can never be NULL.

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

One reason I actually find this useful is when using an ORM and you do not want the resulting value mapped to a nullable type. It can make things easier all around if your application sees the value as never possibly being null. Then you don't have to write code to handle null exceptions, etc.

汹涌人海 2024-08-29 18:25:36

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

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

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

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

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

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

FYI, for people running into this message, adding the ISNULL() around the outside of the cast/convert can mess up the optimizer on your view.

We had 2 tables using the same value as an index key but with types of different numerical precision (bad, I know) and our view was joining on them to produce the final result. But our middleware code was looking for a specific data type, and the view had a CONVERT() around the column returned

I noticed, as the OP did, that the column descriptors of the view result defined it as nullable and I was thinking It's a primary/foreign key on 2 tables; why would we want the result defined as nullable?

I found this post, threw ISNULL() around the column and voila - not nullable anymore.

Problem was the performance of the view went straight down the toilet when a query filtered on that column.

For some reason, an explicit CONVERT() on the view's result column didn't screw up the optimizer (it was going to have to do that anyway because of the different precisions) but adding a redundant ISNULL() wrapper did, in a big way.

眼角的笑意。 2024-08-29 18:25:36

ISNULL() 解决方案的小注释。这似乎仅在您提供恒定值作为第二个参数时才有效。

我在将 datetime 列转换为 date 时遇到了这个问题。原来的列是not null,但是在CAST之后它当然变成了null,所以我使用了ISNULL()函数 getdate() 永远不会给出 null

由于某种原因它失败了,所以我尝试使用原始列,该列也是不可为空的,并且结果相同。最后,当我在那里放置恒定的日期时,我成功了。

 CREATE OR ALTER VIEW dbo.TestView AS
 SELECT 
    MyNotNullDatetimeColumn AS NonNullDatetime,
    ISNULL(CAST(MyNotNullDatetimeColumn AS DATE), GETDATE()) AS NullableDate,
    ISNULL(CAST(MyNotNullDatetimeColumn AS DATE), MyNotNullDatetimeColumn) AS StillNullableDate,
    ISNULL(CAST(MyNotNullDatetimeColumn AS DATE), '20010101') AS NonNullableDate
 FROM dbo.MyTable;

small note to ISNULL() solution. This seems to work only if you provide a constant value as the second argument.

I was fighting with this while casting datetime column to date. The original column was not null, but after CAST it became null of course, so I used ISNULL() with function getdate() that never gives null.

It failed for some reason, so I tried to use original column which also is non-nullable with the same result. Finally I succeeded when I put constant date there.

 CREATE OR ALTER VIEW dbo.TestView AS
 SELECT 
    MyNotNullDatetimeColumn AS NonNullDatetime,
    ISNULL(CAST(MyNotNullDatetimeColumn AS DATE), GETDATE()) AS NullableDate,
    ISNULL(CAST(MyNotNullDatetimeColumn AS DATE), MyNotNullDatetimeColumn) AS StillNullableDate,
    ISNULL(CAST(MyNotNullDatetimeColumn AS DATE), '20010101') AS NonNullableDate
 FROM dbo.MyTable;
も星光 2024-08-29 18:25:36

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

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

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

All you can do in a Select statement is control the data that the database engine sends to you as a client. The select statement has no effect on the structure of the underlying table. To modify the table structure you need to execute an Alter Table statement.

  1. First make sure that there are currently no nulls in that bit field in the table
  2. Then execute the following ddl statement:
    Alter Table dbo.Product Alter column status bit not null

If, otoh, all you are trying to do is control the output of the view, then what you are doing is sufficient. Your syntax will guarantee that the output of the HasStatus column in the views resultset will in fact never be null. It will always be either bit value = 1 or bit value = 0. Don't worry what the object explorer says...

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文