如何使视图列NOT NULL
我想创build一个视图,我希望列只能是真或假。 但是,似乎无论我做什么,SQL Server(2008)都认为我的位列可以以某种方式为空。
我有一个名为“Product”的表,其中列“状态”是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
如果我将这个查询保存为一个视图并查看对象资源pipe理器中的列,则HasStatus列设置为BIT, NULL
。 但它不应该是NULL。 是否有一些神奇的SQL技巧,我可以用来强制这个列NOT NULL
。
请注意,如果我在CASE
周围删除了CAST()
,则该列将被正确设置为NOT NULL
,但是该列的types将设置为INT
,这不是我想要的。 我希望它是BIT
。 🙂
你可以通过重新安排你的查询来达到你想要的。 诀窍是,SQL Server必须先了解ISNULL
,否则结果值不能为NULL
。
SELECT ISNULL(CAST( CASE Status WHEN 3 THEN 1 ELSE 0 END AS bit), 0) AS HasStatus FROM dbo.Product
我实际上发现这个有用的一个原因是使用ORM时,并且不希望结果值映射到可为空的types。 如果您的应用程序将该值视为不可能为空,它可以使事情变得更容易。 那么你不必编写代码来处理空的exception等。
仅供参考,对于遇到此消息的人来说,在cast / convert的外部添加ISNULL()可能会导致视图上的优化器混乱。
我们有两个表使用相同的值作为索引键,但具有不同数值精度的types(我知道是不好的),我们的观点正在join他们以产生最终结果。 但是我们的中间件代码正在寻找一个特定的数据types,并且视图在返回的列周围有一个CONVERT()
我注意到,正如OP所做的那样,视图结果的列描述符将其定义为可空,我想这是2个表的主键/外键; 为什么我们要把结果定义为可空?
我find了这个post,把ISNULL()扔到了列上,呃 – 不能再空了。
问题是当查询在该列上过滤时,视图的performance直奔厕所。
出于某种原因,在视图的结果列上显式的CONVERT()并没有把优化器弄糟(因为不同的精度,它必须这样做),但是添加一个冗余的ISNULL()包装器,办法。
这是我使用的代码,它将使ID列NOT NULL和所有其他的NULL。 您必须转换位或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 aa 1 1 2 2
心连心
您在Select语句中所做的所有操作都是控制数据库引擎作为客户机发送给您的数据。 select语句对基础表的结构没有影响。 要修改表结构,您需要执行一个Alter Table语句。
- 首先确保表中该位字段当前没有空值
- 然后执行以下ddl语句:
Alter Table dbo.Product Alter column status bit not null
如果otoh,你所要做的只是控制视图的输出,那么你所做的就足够了。 您的语法将保证视图结果集中的HasStatus列的输出实际上不会为空。 它始终是位值= 1或位值= 0.不要担心对象浏览器说什么…
DROP TABLE [dbo].[myTable1] GO CREATE TABLE [dbo].[myTable1]( [a] [int] NULL, [b] [varchar](50), ) ON [PRIMARY] GO INSERT INTO [dbo].[myTable1]([a],[b]) VALUES(1,'A'); INSERT INTO [dbo].[myTable1]([a],[b]) VALUES(2,'B'); INSERT INTO [dbo].[myTable1]([a],[b]) VALUES(3,'C'); INSERT INTO [dbo].[myTable1]([a],[b]) VALUES(4,'D'); INSERT INTO [dbo].[myTable1]([a],[b]) VALUES(5,NULL); SELECT *, (CASE b WHEN NULL THEN CAST(0 AS BIT) WHEN 'A' THEN CAST(1 AS BIT) WHEN 'B' THEN CAST(0 AS BIT) ELSE CAST(0 AS BIT) END) AS Status FROM dbo.myTable1