powered by simpleCommunicator - 2.0.49     © 2025 Programmizd 02
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / Триггер
25 сообщений из 91, страница 1 из 4
Триггер
    #37842272
Sky Dragon
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Здравствуйте!
Сегодня впервые столкнулся с SQL. Задача такая(на пальцах):
есть таблица ("MyTable"). В ней 2 поля: Field1 и Field2.
так вот, необходимо при изменении, если поле Field1 == null, то и Field2 тоже обнулить.
Как я понял, делается это с помощью триггера. Написал что-то типа:

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
USE [MyDB]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO

ALTER TRIGGER [dbo].[nuller_trigger]
ON [MyDB].[dbo].[MyTable]
AFTER UPDATE 
AS
   DECLARE @field1 int
   SELECT @field1 = Field1   
   FROM MyTable
IF(@field1 =null)
UPDATE MyTable
SET Field2 = null



не обнуляет. Почему то еще есть сомнения, что зациклится такое обновление, ведь всегда будет вызываться UPDATE )
Подскажите пожалуйста, как правильно? Времени читать учебники просто нет, так как это разовая задачка.
...
Рейтинг: 0 / 0
Триггер
    #37842279
Фотография tpg
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Sky Dragon...не обнуляет...Не удивительно...
Триггер написан из предположения, что он вызывается для каждой измененной строки. Это не так.
...
Рейтинг: 0 / 0
Триггер
    #37842283
Sky Dragon
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
tpg,

подскажите пожалуйста тогда, как сделать, чтобы было "так" :)
...
Рейтинг: 0 / 0
Триггер
    #37842293
iap
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Sky Dragontpg,

подскажите пожалуйста тогда, как сделать, чтобы было "так" :)1. Сравнивать поля/переменные с NULL операторами =,<>,<,> и т.п. нельзя!
2. Старайтесь не использовать скалярные переменные в триггерах.
3. Используйте псевдотаблицы deleted и inserted
...
Рейтинг: 0 / 0
Триггер
    #37842297
iap
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
4. За UPDATE без WHERE надо расстреливать! (За редким исключением)
...
Рейтинг: 0 / 0
Триггер
    #37842299
Фотография tpg
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
... и ничего не сказано о наличии ПК или ещё какого уникального столбца.
...
Рейтинг: 0 / 0
Триггер
    #37842301
iap
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
iap4. За UPDATE без WHERE надо расстреливать! (За редким исключением)WHERE или INNER JOIN или CROSS APPLY, если точнее
...
Рейтинг: 0 / 0
Триггер
    #37842584
Winnipuh
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
iap4. За UPDATE без WHERE надо расстреливать! (За редким исключением)

всех не перестреляешь!
...
Рейтинг: 0 / 0
Триггер
    #37842641
RubinDm
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
alter trigger [dbo].[nuller_trigger]
  on [MyDB].[dbo].[MyTable] after update
as
begin

  -- Если UPDATE не задел поле [Field1], то ...
  if (not(update(Field1)))
    return; -- нет необходимости в сбросе значения поля [Field2] в NULL

  -- Если UPDATE не задел записи таблицы, то ...
  if (not(exists(select * from [inserted]))
    return; -- нет необходимости в сбросе значения поля [Field2] в NULL

  -- Проверяем наличие записей, в которых
  -- значение поля [Field1] было сброшено в NULL.
  if (not(exists(
    select [new].[ID]
    from [inserted] [new]
    join [deleted]  [old] on [old].[ID] = [new].[ID]
    where [old].Field1 is NOT null
      and [new].Field1 is null
  )))
    return; -- нет необходимости в сбросе значения поля [Field2] в NULL
  
  -- Сброс значения поля [Field2] в NULL
  update T set T.Field2 = null
  from MyTable T
  where T.[ID] in ( -- тут мы вычисляем ID записей, в которых
                    -- значение поля [Field1] было сброшено в NULL.
                    select [new].[ID]
                    from [inserted] [new]
                    join [deleted]  [old] on [old].[ID] = [new].[ID]
                    where [old].Field1 is NOT null
                      and [new].Field1 is null
                  )
  
  return;

end
go



зы: не проверял (ибо не на чем)
...
Рейтинг: 0 / 0
Триггер
    #37842926
iap
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
RubinDm,

применение функции UPDATE() - абсолютно бессмысленно
...
Рейтинг: 0 / 0
Триггер
    #37843103
Xordal
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Да и 2 раза выполнять:
Код: sql
1.
2.
3.
4.
5.
    select [new].[ID]
    from [inserted] [new]
    join [deleted]  [old] on [old].[ID] = [new].[ID]
    where [old].Field1 is NOT null
      and [new].Field1 is null


думаю тоже ни к чему.
...
Рейтинг: 0 / 0
Триггер
    #37843134
invm
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Xordal,

В общем-то, даже и один раз ни к чему.
...
Рейтинг: 0 / 0
Триггер
    #37843192
RubinDm
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
iapRubinDm, применение функции UPDATE() - абсолютно бессмысленноНе могли бы Вы аргументировать Ваш комент?
...
Рейтинг: 0 / 0
Триггер
    #37843193
RubinDm
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
XordalДа и 2 раза выполнять:
Код: sql
1.
2.
3.
4.
5.
    select [new].[ID]
    from [inserted] [new]
    join [deleted]  [old] on [old].[ID] = [new].[ID]
    where [old].Field1 is NOT null
      and [new].Field1 is null


думаю тоже ни к чему.И Вы... не могли бы Вы аргументировать Ваш комент?
...
Рейтинг: 0 / 0
Триггер
    #37843195
RubinDm
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
invmXordal, В общем-то, даже и один раз ни к чему.И Вы... не могли бы Вы аргументировать Ваш комент?
...
Рейтинг: 0 / 0
Триггер
    #37843240
iap
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
RubinDmiapRubinDm, применение функции UPDATE() - абсолютно бессмысленноНе могли бы Вы аргументировать Ваш комент?А можно сначала услышать Ваш комментарий по этому поводу?
...
Рейтинг: 0 / 0
Триггер
    #37843256
invm
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
RubinDminvmXordal, В общем-то, даже и один раз ни к чему.И Вы... не могли бы Вы аргументировать Ваш комент?
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
alter trigger [dbo].[nuller_trigger]
  on [MyDB].[dbo].[MyTable] after update
as
begin

  -- Если UPDATE не задел поле [Field1], то ...
  if (not(update(Field1)))
    return; -- нет необходимости в сбросе значения поля [Field2] в NULL

  -- Если UPDATE не задел записи таблицы, то ...
  if (not(exists(select * from [inserted]))
    return; -- нет необходимости в сбросе значения поля [Field2] в NULL

  -- Сброс значения поля [Field2] в NULL
  update T
   set
    T.Field2 = null
  from
   inserted i join
   deleted d on d.[ID] = i.[ID] join
   MyTable T on t.[ID] = i.[ID]
  where
   i.Field1 is null and d.Field1 is not null;

 return;
end
go
...
Рейтинг: 0 / 0
Триггер
    #37843303
RubinDm
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
iapRubinDmпропущено...Не могли бы Вы аргументировать Ваш комент?А можно сначала услышать Ваш комментарий по этому поводу?Можно. Я всегда рад помочь незрячим и слабовидящим:
Код: sql
1.
2.
3.
-- Если UPDATE не задел поле [Field1], то ...
  if (not(update(Field1)))
    return; -- нет необходимости в сбросе значения поля [Field2] в NULL

Теперь не могли бы Вы аргументировать Ваш комент?
...
Рейтинг: 0 / 0
Триггер
    #37843311
iap
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
RubinDmiapпропущено...
А можно сначала услышать Ваш комментарий по этому поводу?Можно. Я всегда рад помочь незрячим и слабовидящим:
Код: sql
1.
2.
3.
-- Если UPDATE не задел поле [Field1], то ...
  if (not(update(Field1)))
    return; -- нет необходимости в сбросе значения поля [Field2] в NULL

Теперь не могли бы Вы аргументировать Ваш комент?"Задел поле" - это как понимать?
...
Рейтинг: 0 / 0
Триггер
    #37843338
RubinDm
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
iapRubinDmпропущено...
Можно. Я всегда рад помочь незрячим и слабовидящим:
Код: sql
1.
2.
3.
-- Если UPDATE не задел поле [Field1], то ...
  if (not(update(Field1)))
    return; -- нет необходимости в сбросе значения поля [Field2] в NULL

Теперь не могли бы Вы аргументировать Ваш комент?"Задел поле" - это как понимать?
1) Этот запрос задевает (меняет) значение поля Field1 и не задевает (не меняет) значение поля Field2.
Код: sql
1.
update T set Field1 = ... from MyTable T


2) Этот запрос задевает (меняет) значение поля Field2 и не задевает (не меняет) значение поля Field1.
Код: sql
1.
update T set Field2 = ... from MyTable T


3) Этот запрос задевает (меняет) значения обоих полей.
Код: sql
1.
update T set Field1 = ..., Field2 = ... from MyTable T


По условиям поставленной автором топика задачи интерес представляют только те случаи, в которых значение поля Field1 может быть изменено (примеры 1 и 3). В противном случае (пример 2) актуализация поля Field2 не требуется, т.к. Field1 не меняется и ловить там нечего в принципе.

Так я увижу Ваши аргументы или забудем об этом?
...
Рейтинг: 0 / 0
Триггер
    #37843649
Xordal
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
RubinDmXordalДа и 2 раза выполнять:
Код: sql
1.
2.
3.
4.
5.
    select [new].[ID]
    from [inserted] [new]
    join [deleted]  [old] on [old].[ID] = [new].[ID]
    where [old].Field1 is NOT null
      and [new].Field1 is null


думаю тоже ни к чему.И Вы... не могли бы Вы аргументировать Ваш комент?
Ну это условие как минимум один раз будет проверяться, а в случае если есть что апдейтить, то даже 2 раза. Зачем серверу лишнюю работу давать? И, как отметил invm, в update ... set ... подзапрос не нужен, можно сразу джойниться на таблицы inserted и deleted
...
Рейтинг: 0 / 0
Триггер
    #37843665
Фотография alexeyvg
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
2 RubinDm

Код: sql
1.
if (not(update(Field1)))

это полезный стейтмент, позволит уменьшить нагрузку на сервер

Код: sql
1.
if (not(exists(select * from [inserted]))

не нужно, обновление и так не будет потреблять ресурсов, если в inserted ничего нет.

Код: sql
1.
2.
if (not(exists(
    select [new].[ID] ...

не нужно, запрос в update сделает то же самое.

А из обновления можно убрать лишний джойн:
Код: sql
1.
2.
3.
4.
5.
6.
7.
-- Сброс значения поля [Field2] в NULL
  update T
  set T.Field2 = null
  from deleted d
   MyTable T on T.[ID] = d.[ID]
  where
    T.Field1 is null and d.Field1 is not null;
...
Рейтинг: 0 / 0
Триггер
    #37843694
Sky Dragon
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Ого, сколько обсуждений вызвал такой маленький вопрос)
Из одних только комментариев уже можно выучить синтаксис SQL )

Всем спасибо, что откликнулись
...
Рейтинг: 0 / 0
Триггер
    #37844090
iap
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
RubinDmiapпропущено...
"Задел поле" - это как понимать?
1) Этот запрос задевает (меняет) значение поля Field1 и не задевает (не меняет) значение поля Field2.
Код: sql
1.
update T set Field1 = ... from MyTable T


2) Этот запрос задевает (меняет) значение поля Field2 и не задевает (не меняет) значение поля Field1.
Код: sql
1.
update T set Field2 = ... from MyTable T


3) Этот запрос задевает (меняет) значения обоих полей.
Код: sql
1.
update T set Field1 = ..., Field2 = ... from MyTable T


По условиям поставленной автором топика задачи интерес представляют только те случаи, в которых значение поля Field1 может быть изменено (примеры 1 и 3). В противном случае (пример 2) актуализация поля Field2 не требуется, т.к. Field1 не меняется и ловить там нечего в принципе.

Так я увижу Ваши аргументы или забудем об этом?Кто кого "задевает" в этом примере:
Код: sql
1.
update T set Field1 = Field1, Field2 = Field2 from MyTable T

?
...
Рейтинг: 0 / 0
Триггер
    #37844112
RubinDm
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
iapКто кого "задевает" в этом примере:
Код: sql
1.
update T set Field1 = Field1, Field2 = Field2 from MyTable T

?Задевает поля инструкция, в данном случае это update , который задевает два поля: Field1 и Field2. Тот факт, что значения полей фактически не должны изменится, вовсе не означает, что сервер не должен выполнять инструкцию update. Сервер понимает, что могут быть тригеры, которые также могут влиять на результат выполнения инструкции. Возможно, что сервер понимает еще много разного, о чем мы даже не догадываемся. При этом полей в таблице иногда бывает много, но не всегда все из них подвергаются воздействиям инструкции update. И в тригерах, как правило, надо отлавливать изменение только конкретного набора полей, как в случае задачи поставленной автором топика. Вызов функции update(Field1) отвечает на вопрос, было ли упомянуто поле Field1 в инструкции update в части set. Если не было, но нет никакой необходимости в актуализации Field2.
...
Рейтинг: 0 / 0
25 сообщений из 91, страница 1 из 4
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / Триггер
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]