Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Microsoft SQL Server Новый топик    Ответить
 Триггер, как сделать корректно  [new]
Challenger
Member

Откуда: Москва
Сообщений: 436
Уважаемые, коллеги.

Как корректно в триггере запретить обновление таблицы, если есть запись удовлетворяющая определенным требованиям?
(id_center=@id_center) AND (ABS(DATEDIFF(minute,time_screening,@time_screening))<=2) AND (DATEDIFF(minute,ts,@dt)<20) and (id_user<>@id_user)

Следующий триггер не работает. Так как в таблице j_screening виден уже новый вариант записи после обновления.

Может быть можно как то по другому его переписать?

Считаем, что в таблице INSERTED всегда одна запись, поэтому не используем JOIN.

ALTER TRIGGER [dbo].[trJ_Screening_AfterInsert]
ON [dbo].[j_screening]
AFTER INSERT,UPDATE
AS
BEGIN
SET NOCOUNT ON;
DECLARE @id_center int,
@time_screening datetime,
@id int,
@F varchar(250),
@id_user int,
@id_user2 int,
@dt datetime,
@id2 int

SET @dt = GETDATE()

SELECT @id=id,@id_center=id_center,@time_screening=time_screening,@F=F,@id_user=id_user
FROM INSERTED


IF (EXISTS(
SELECT *
FROM j_screening
WHERE (id_center=@id_center) AND (ABS(DATEDIFF(minute,time_screening,@time_screening))<=2) AND (DATEDIFF(minute,ts,@dt)<20) and (id_user<>@id_user)
))
BEGIN
RAISERROR ('Запись на это время уже занята другим оператором', 16, 1);
ROLLBACK TRAN
RETURN
END


END

Из клиента обновление таблицы производится через EXECSQL, внутри, которого вызывается INSERT и UPDATE
29 июл 13, 15:27    [14632596]     Ответить | Цитировать Сообщить модератору
 Re: Триггер, как сделать корректно  [new]
Сергей Викт.
Member

Откуда: Москва
Сообщений: 888
+ Многа букафф
Challenger
Уважаемые, коллеги.

Как корректно в триггере запретить обновление таблицы, если есть запись удовлетворяющая определенным требованиям?
(id_center=@id_center) AND (ABS(DATEDIFF(minute,time_screening,@time_screening))<=2) AND (DATEDIFF(minute,ts,@dt)<20) and (id_user<>@id_user)

Следующий триггер не работает. Так как в таблице j_screening виден уже новый вариант записи после обновления.

Может быть можно как то по другому его переписать?

Считаем, что в таблице INSERTED всегда одна запись, поэтому не используем JOIN.

ALTER TRIGGER [dbo].[trJ_Screening_AfterInsert]
ON [dbo].[j_screening]
AFTER INSERT,UPDATE
AS
BEGIN
SET NOCOUNT ON;
DECLARE @id_center int,
@time_screening datetime,
@id int,
@F varchar(250),
@id_user int,
@id_user2 int,
@dt datetime,
@id2 int

SET @dt = GETDATE()

SELECT @id=id,@id_center=id_center,@time_screening=time_screening,@F=F,@id_user=id_user
FROM INSERTED


IF (EXISTS(
SELECT *
FROM j_screening
WHERE (id_center=@id_center) AND (ABS(DATEDIFF(minute,time_screening,@time_screening))<=2) AND (DATEDIFF(minute,ts,@dt)<20) and (id_user<>@id_user)
))
BEGIN
RAISERROR ('Запись на это время уже занята другим оператором', 16, 1);
ROLLBACK TRAN
RETURN
END


END

Из клиента обновление таблицы производится через EXECSQL, внутри, которого вызывается INSERT и UPDATE



А у вас же триггер AFTER написан? Он отрабатывает ПОСЛЕ вставки записи. Попробуйте FOR или INSTEAD OFF
29 июл 13, 15:31    [14632627]     Ответить | Цитировать Сообщить модератору
 Re: Триггер, как сделать корректно  [new]
qwerty112
Guest
>> Может быть можно как то по другому его переписать?

INSTEAD OF TRIGGER

>> Считаем, что в таблице INSERTED всегда одна запись, поэтому не используем JOIN.

гыы

зы
уважаемого коллегу, не затруднит, выкладывать код, в тегах оформления кода ?
29 июл 13, 15:32    [14632629]     Ответить | Цитировать Сообщить модератору
 Re: Триггер, как сделать корректно  [new]
qwerty112
Guest
Сергей Викт.
А у вас же триггер AFTER написан? Он отрабатывает ПОСЛЕ вставки записи. Попробуйте FOR или INSTEAD OFF

FOR и AFTER - "синонимы"
29 июл 13, 15:33    [14632640]     Ответить | Цитировать Сообщить модератору
 Re: Триггер, как сделать корректно  [new]
Гость333
Member

Откуда:
Сообщений: 3683
Challenger,

Добавьте в WHERE условие pk <> @pk, где pk — первичный ключ вашей таблицы.
Ну и триггер ваш состоит из г-кода, ибо "Считаем, что в таблице INSERTED всегда одна запись" — это плохо, очень плохо.

Сергей Викт.
Попробуйте FOR

FOR и AFTER — одно и то же в случае триггеров.
29 июл 13, 15:36    [14632666]     Ответить | Цитировать Сообщить модератору
 Re: Триггер, как сделать корректно  [new]
Challenger
Member

Откуда: Москва
Сообщений: 436
Гость333
Challenger,

Добавьте в WHERE условие pk <> @pk, где pk — первичный ключ вашей таблицы.
Ну и триггер ваш состоит из г-кода, ибо "Считаем, что в таблице INSERTED всегда одна запись" — это плохо, очень плохо.

Сергей Викт.
Попробуйте FOR

FOR и AFTER — одно и то же в случае триггеров.


Мы никогда не попадаем итак в if. И без этого условия. Так как в таблице уже видны данные после модификации.
Считаем, что в INSERT одна запись для упрощения ситуации здесь.
29 июл 13, 15:47    [14632772]     Ответить | Цитировать Сообщить модератору
 Re: Триггер, как сделать корректно  [new]
iap
Member

Откуда: Москва
Сообщений: 47085
Challenger
(id_center=@id_center) AND (ABS(DATEDIFF(minute,time_screening,@time_screening))<=2) AND (DATEDIFF(minute,ts,@dt)<20) and (id_user<>@id_user)
    id_center=@id_center
AND time_screening>=DATEADD(MINUTE,-2,@time_screening)
AND time_screening<=DATEADD(MINUTE,2,@time_screening)
AND ts>DATEADD(MINUTE,-20,@dt)
AND id_user<>@id_user
29 июл 13, 15:50    [14632790]     Ответить | Цитировать Сообщить модератору
 Re: Триггер, как сделать корректно  [new]
iap
Member

Откуда: Москва
Сообщений: 47085
Challenger
Гость333
Challenger,

Добавьте в WHERE условие pk <> @pk, где pk — первичный ключ вашей таблицы.
Ну и триггер ваш состоит из г-кода, ибо "Считаем, что в таблице INSERTED всегда одна запись" — это плохо, очень плохо.

пропущено...

FOR и AFTER — одно и то же в случае триггеров.


Мы никогда не попадаем итак в if. И без этого условия. Так как в таблице уже видны данные после модификации.
Считаем, что в INSERT одна запись для упрощения ситуации здесь.
1. Выбросьте из триггера все скалярные переменные.
2. используйте таблицы deleted и inserted
3. считайте, что в inserted 1 миллион записей!
29 июл 13, 15:53    [14632828]     Ответить | Цитировать Сообщить модератору
 Re: Триггер, как сделать корректно  [new]
Сергей Викт.
Member

Откуда: Москва
Сообщений: 888
qwerty112
Сергей Викт.
А у вас же триггер AFTER написан? Он отрабатывает ПОСЛЕ вставки записи. Попробуйте FOR или INSTEAD OFF

FOR и AFTER - "синонимы"

Да, ошибся, прошу прощения.
29 июл 13, 16:03    [14632905]     Ответить | Цитировать Сообщить модератору
 Re: Триггер, как сделать корректно  [new]
Гость333
Member

Откуда:
Сообщений: 3683
Challenger
Мы никогда не попадаем итак в if. И без этого условия. Так как в таблице уже видны данные после модификации.

Поясните на каком-нибудь примере.
29 июл 13, 16:10    [14632958]     Ответить | Цитировать Сообщить модератору
 Re: Триггер, как сделать корректно  [new]
Challenger
Member

Откуда: Москва
Сообщений: 436
iap,

спасибо, через таблицу deleted все получилось.
29 июл 13, 16:18    [14633016]     Ответить | Цитировать Сообщить модератору
 Re: Триггер, как сделать корректно  [new]
iap
Member

Откуда: Москва
Сообщений: 47085
Challenger
iap,

спасибо, через таблицу deleted все получилось.
Ответ на вопрос "как сделать корректно?" -
это минимум три пункта, которые я перечислил.
К тому же это в AFTER UPDATE deleted заполнена.
А у Вас же ещё INSERT бывает с этим же триггером?
29 июл 13, 16:22    [14633038]     Ответить | Цитировать Сообщить модератору
Все форумы / Microsoft SQL Server Ответить