Во-первых, если вы пытаетесь гарантировать, что url
s уникальны, то используйте ограничение уникальности:
alter table foo add constraint unq_foo_url unique (url);
Во-вторых, НИКОГДА не предполагайте, что inserted
имеет только одну строку. Этот код:
SELECT @Url = ins.Url from INSERTED ins;
- это ошибка, ожидающая своего появления.
РЕДАКТИРОВАТЬ:
Если у вас есть таблица, которая уже нарушает ограничение уникальности, у вас возникла грязная проблема. Вы можете решить эту проблему. Проблема с вашим кодом в том, что триггер FOR INSERT
действительно является триггером AFTER INSERT
- новые данные уже видны.
Но вы можете справиться с этим. Вот один из способов:
CREATE TRIGGER [dbo].[FooInsertTrigger]
ON [dbo].[Foo]
AFTER INSERT
AS
BEGIN
IF (SELECT TOP (1) COUNT(*)
FROM inserted i JOIN
[dbo].[Foo] f
on i.url = f.url
GROUP BY i.url
ORDER BY COUNT(*) DESC
) > 1
BEGIN
RAISERROR('Duplicate URL found' , 16, 1);
ROLLBACK TRANSACTION;
RETURN
END;
PRINT 'Executed Trigger Insert.'
END;
Максимум count(*)
больше 1 в следующих случаях:
inserted.url
соответствует 1 строке в foo
. Это нормальный случай. inserted.url
соответствует нескольким строкам в foo
. Это поймано.
Это также поймает случай, когда есть кратные числа в inserted
.
Делая код безопасным для нескольких вставок, труднее вытащить оскорбительные URL. Но ошибка обрабатывается правильно.
Здесь - это db <> скрипка.