0
点赞
收藏
分享

微信扫一扫

SQLServer 表字段为 NULL 而视图为NOT NULL 问题


之前有处理几次这个问题,不过还是简单记录下来吧。


--  创建测试表和视图

-- DROP DATABASE Demo;
CREATE DATABASE Demo;
GO
USE Demo
GO

-- DROP TABLE [dbo].[TestTable]
CREATE TABLE [dbo].[TestTable](
[Identifier] [uniqueidentifier] NOT NULL,
[Name] [varchar](50) NULL,
[value] [numeric](18, 4) NULL
) ON [PRIMARY]
GO

ALTER TABLE [dbo].[TestTable]
ADD CONSTRAINT [PK_TestTable] PRIMARY KEY CLUSTERED([Identifier])
GO

ALTER TABLE [dbo].[TestTable]
ADD CONSTRAINT [DF_TestTable_Identifier] DEFAULT (newsequentialid()) FOR [Identifier]
GO


-- DROP VIEW [dbo].[VTestTable]
CREATE VIEW [dbo].[VTestTable]
AS
SELECT [Identifier],[Name],[value]
FROM dbo.TestTable
GO

SQLServer  表字段为 NULL 而视图为NOT NULL 问题_默认值




插入数据到视图(正常):

INSERT INTO [VTestTable]([Identifier],[Name],[value])
SELECT NEWID(),'KK',NULL
GO

UPDATE [VTestTable] SET [value]=NULL
GO



由于字段[value]没有默认值,读取或插入数据时null改为0 :

--  由于字段[value]没有默认值,读取或插入数据时null改为0
ALTER VIEW [dbo].[VTestTable]
AS
SELECT [Identifier],[Name],ISNULL([value],0) [value]
FROM dbo.TestTable
GO


此时看到,视图中的字段 [value] 为 not null :

SQLServer  表字段为 NULL 而视图为NOT NULL 问题_解决方法_02


此时对视图更新或插入失败:

--  此时对视图更新或插入失败
INSERT INTO [VTestTable]([Identifier],[Name],[value])
SELECT NEWID(),'KK',NULL
GO

UPDATE [VTestTable] SET [value]=NULL
GO


消息 4406,级别 16,状态 1,第 1 行

对视图或函数 'VTestTable' 的更新或插入失败,因其包含派生域或常量域。



原因是:视图不允许为NULL!


解决方法(一):

--  解决方法(一):增加触发器
-- DROP TRIGGER [dbo].[tr_VTestTable_insert]
CREATE TRIGGER [dbo].[tr_VTestTable_insert]
ON DBO.[VTestTable]
INSTEAD OF INSERT
AS
BEGIN
INSERT INTO TestTable([Name],[value])
SELECT [Name],ISNULL([value],0) FROM inserted;
END
GO

-- DROP TRIGGER [dbo].[tr_VTestTable_update]
CREATE TRIGGER [dbo].[tr_VTestTable_update]
ON DBO.[VTestTable]
INSTEAD OF UPDATE
AS
BEGIN
UPDATE t1 SET
t1.[Name] = t2.[Name],
t1.[value] = ISNULL(t2.[value],0)
FROM TestTable AS t1, inserted AS t2 WHERE t1.[Identifier] = t2.[Identifier]
END
GO


--  此时操作正常!
INSERT INTO [VTestTable]([Identifier],[Name],[value])
SELECT NEWID(),'KK',NULL
GO
UPDATE [VTestTable] SET [value]=NULL --更新为null,触发器替换为0
GO


解决方法(二):

--  解决方法(二):增加默认值约束

/*--删除刚创建的对象
DROP TRIGGER [dbo].[tr_VTestTable_insert]
DROP TRIGGER [dbo].[tr_VTestTable_update]
*/

-- 增加默认值约束
ALTER TABLE [dbo].[TestTable]
ADD CONSTRAINT [DF_TestTable_value] DEFAULT (0) FOR [value]
GO

-- 更新表中原有为 NULL 的值
UPDATE [dbo].[TestTable] SET [value] = 0
GO

--修改视图
ALTER VIEW [dbo].[VTestTable]
AS
SELECT [Identifier],[Name],[value]
FROM dbo.TestTable
GO



--  插入时不显示插入,[value] 默认为0;
INSERT INTO [VTestTable]([Identifier],[Name])
SELECT NEWID(),'KK'
GO

-- 此时允许更新为 NULL !
UPDATE [VTestTable] SET [value]=NULL
GO




举报

相关推荐

0 条评论