坚持创建触发器

问题描述

| 执行一些MSSQL练习,而我正在尝试创建一个触发器。但是,从理论上讲,我所拥有的解决方案对我来说是正确的,但它不起作用。 目的是为只有两列的表创建触发器。一栏是主键,是身份,不允许空值。另一列是允许NULL值的列。但是,它只允许在整个表中为单行提​​供NULL值。基本上,应该为该表上的插入/更新操作触发一个触发器,当表中该列已存在一个空值时,该触发器将尝试将该列插入/更新为空值。 我在触发代码中捕获了这种情况,如下所示:
After Insert,Update
AS 
set ANSI_WARNINGS OFF
If ( (select count(NoDupName) from TestUniqueNulls where NoDupName is null) > 1 )
BEGIN
Print \'There already is a row that contains a NULL value,transaction aborted\';
ROLLBACK TRAN
END
但是,事务仍然会自行执行。我不知道为什么会这样,并且触发器没有触发自身。 那么有人在这里启发我的疑虑吗? 我还使用了在触发器开始时设置ANSI_WARNINGS OFF的功能。     

解决方法

        
count(col)
仅计算非空值,因此
count(NoDupName) ...  where NoDupName is null
将始终为零。您需要改为选择
count(*)
。 我意识到这只是一个练习,但是索引视图可能是一个更好的机制。
CREATE VIEW dbo.NoMoreThanOneNull
WITH SCHEMABINDING
AS
SELECT NoDupName
FROM dbo.TestUniqueNulls
WHERE NoDupName IS NULL

GO

CREATE UNIQUE CLUSTERED INDEX ix ON dbo.NoMoreThanOneNull(NoDupName)
    ,        是的,这是一个陷阱。 COUNT的括号内的表达式的计算结果必须为非null,否则将不计算在内。因此,在表达式中使用
*
1
或任何不可为空的列更为安全。尽管您也可以遇到\'1 \',但最常遇到的表达式是
\'*\'
。在性能方面,这些表达式之间没有区别。但是,如果您使用可以求值为null的表达式(如nullable列),则计数和其他聚合可能会完全不可用。
create table nulltest(a int null)
go
insert nulltest(a) values (1),(null),(2)
go
select * from nulltest
select COUNT(*) from nulltest
select COUNT(1) from nulltest
select COUNT(a) from nulltest
go
drop table nulltest
    

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...