Застрял в создании триггера - PullRequest
2 голосов
/ 28 мая 2011

выполняет некоторые упражнения MSSQL, и я пытаюсь создать триггер.Тем не менее, решение, которое я имею, кажется мне теоретически правильным, но оно не работает.

Цель состоит в том, чтобы создать триггер для таблицы, которая имеет только два столбца.Один столбец является первичным ключом и является идентификатором и не допускает нулевые значения.Другой столбец разрешает значения NULL.Тем не менее, он допускает значения NULL ТОЛЬКО ДЛЯ ОДНОЙ СТРОКИ во всей таблице.По сути, триггер должен срабатывать для операции вставки / обновления в этой таблице, которая пытается вставить / обновить столбец до значения 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

Тем не менее транзакция выполняется сама по себе.Я не уверен, почему это происходит, и триггер не срабатывает сам по себе.

Так, кто-нибудь, чтобы просветить мои опасения здесь?

Я также использовал set ANSI_WARNINGS OFF в начале триггера.

Ответы [ 2 ]

2 голосов
/ 28 мая 2011

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)
0 голосов
/ 28 мая 2011

Да, это гоча.Выражение в паренях СЧЕТА должно вычисляться как ненулевое, иначе оно не будет засчитано.Поэтому безопаснее использовать *, или 1, либо любой необнуляемый столбец в выражении.Наиболее часто встречающееся выражение - '*', хотя вы также можете встретить «1».Нет разницы между этими выражениями с точки зрения производительности.Однако, если вы используете выражение, которое может иметь нулевое значение (например, столбец с нулевым значением), ваши значения и другие агрегаты могут быть полностью отключены.

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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...